From d021817637eed1de862d313b3ea934e2c12667d0 Mon Sep 17 00:00:00 2001 From: "makoto.nishizawa" Date: Mon, 22 Jul 2019 11:35:08 +0900 Subject: [PATCH] applied to new question model --- Makefile | 14 + io.c | 5 +- io.h | 1 + io.o | Bin 0 -> 5768 bytes main.cpp | 1 - main.o | Bin 0 -> 11296 bytes makefile | 6 +- router/Makefile | 14 + router/README.md | 64 + router/ap_int.h | 521 ++++ router/etc/ap_fixed_sim.h | 2451 ++++++++++++++++ router/etc/ap_int_sim.h | 1629 +++++++++++ router/etc/ap_private.h | 5858 +++++++++++++++++++++++++++++++++++++ router/main.cpp | 69 + router/main.o | Bin 0 -> 3728 bytes router/router.cpp | 338 +++ router/router.hpp | 44 + router/router.o | Bin 0 -> 14816 bytes router/sim | Bin 0 -> 22776 bytes solve | Bin 47184 -> 115208 bytes solver.cpp | 131 +- solver.o | Bin 0 -> 78872 bytes 22 files changed, 11118 insertions(+), 28 deletions(-) create mode 100644 Makefile create mode 100644 io.o create mode 100644 main.o create mode 100644 router/Makefile create mode 100644 router/README.md create mode 100644 router/ap_int.h create mode 100644 router/etc/ap_fixed_sim.h create mode 100644 router/etc/ap_int_sim.h create mode 100644 router/etc/ap_private.h create mode 100644 router/main.cpp create mode 100644 router/main.o create mode 100644 router/router.cpp create mode 100644 router/router.hpp create mode 100644 router/router.o create mode 100644 router/sim create mode 100644 solver.o diff --git a/Makefile b/Makefile new file mode 100644 index 0000000..07645dc --- /dev/null +++ b/Makefile @@ -0,0 +1,14 @@ +TARGET = sim +OBJS = $(CPPS:.cpp=.o) +CPPS = $(wildcard *.cpp) +CXX = g++ +CXXFLAGS = -O3 -DSOFTWARE + +all: $(TARGET) + +$(TARGET): $(OBJS) + $(CXX) -o $@ $(OBJS) + +clean: + rm *.o + rm $(TARGET) diff --git a/io.c b/io.c index bdc07f6..eb5cba4 100644 --- a/io.c +++ b/io.c @@ -14,6 +14,8 @@ short int block_data[MAXBLOCK+1][5][3]; // ブロックの情報 short int board_data[MAXW][MAXH]; // 盤面情報 +short int line_num=0; + void reset_parameters(void){ int i,j,k; for(i=0;iline_num) line_num=num; else if(str[k]==','){ if(num<0){ num=0; diff --git a/io.h b/io.h index 5c6a201..a381334 100644 --- a/io.h +++ b/io.h @@ -30,6 +30,7 @@ extern short int board_data[MAXW][MAXH]; // 盤面情報 // ... // (0,71),(1,71), ... ,(71,71) // 基本的には回答フォーマットに沿う形 +extern short int line_num; void reset_parameters(void); // read_problem に内包 void read_problem(void); diff --git a/io.o b/io.o new file mode 100644 index 0000000000000000000000000000000000000000..8ea0dd67f426d602c90ae6f5a88428db36f8eac1 GIT binary patch literal 5768 zcmdT{U2I!L7M>fYbQ@Bf0t<*DVS&P?-NwXFA|g@A)K9QxVBWJ!5FJRD>{K%~j^$EKil@}T*ayF*v7hPLvD{(i zOkSSDIJKwa>*P7_8-McDix^x#z1a1vJe`J>Ukc?yzBP%Cm<<^yVn6Jr5od|oo|h=Wv{Vm0rGkuF(3&mpWPy(1qEw@k z9`&!2CGVS};`81&|EiY2&5MwI;nWy;(RVgM=-)xzXcdU+SRGmdA1T@?Blc+U#&BqaMA z6X0Z(7I~{KfKy|aJ{30nZX~|er0})IB0?q-@kF=p;9$gw0TL!479HFhbEwt7KOWwP z8Wn{@)ODCDiX)nQ?d=<%*}7eBX>a$5t$*1mL1{;8q)CA8W1FAted_+!h_9!uHL|8P zvI=H!Q*Up#udT0tbl4g7J>p;M?`ZEFRjt4)flhzNT7Mw0%I)wy)Dh_H=S-TQp9Q5&lPw`=CVmThQ(CK^^Vqbo*!< z_6qT5cy49$sn!^J z495Lou^mqBK@k)BxTzu-2{|Fr9}guWZZ)_w(3yxPqfT%nln4z)ooFI?KmhtsA{vSW zM-uV={n4QVA{h=14~UUbCn@$u;S~%foltmRFdW+#90(2WS1Kck!C@yD8crUJCJqSI zQaa&SC;_fk&ce-5$2BDRKvxj=5(wp2x{j-e^9z@Uk{>mW`-bo0rFd{akbf&Y#BbI( z@|VFwvV!4ghxXITI(F`3INBlm57xoE4Er?p2FAy~3}oj?gMWv1^m)eTalOF!7#qoM zhV!^$b?n3$j&{hOm+Roi4f}WNfwPRy<2q&V$xr;eLowIuZN^{jQq=n&4CiruSjWx; z!_f}Kb%LYz%{;MmrUYm8iC5@v#kM~}kj1b4Wh~o8Yob2Fzf$}ipb35G( z=jU-F!|`q;`|dv;_Z;!O^ep4!To8X7!?~S34Cnlq#>xM^=sZY*@$ZB-*+0r~ZhxHN z+g}gemJOc zj0^8O+Hd0q4qZy#(Ky9*K;!>n_IX@B-H&$3HbOo40wH|LZHhg*B%Ho8gg<$B$O-jB z=_K4TMzutAf5`7d4>`iGz8(Di$)xZn;%*}x9~z1dL*H=RiTXD^)7P#(3xI%X(O7T* zKPvRFzq;^&1x&4aIx6;hbZye;&}q2BTM0Ehx;+)dt=PCgAkXPfUu>c-eevQRKzRTj z#C6(1$Q7-p(*mIj)&#*d@Ssgo->3C^UdNTGimzH#wE(F{l@W91F_vg z;QFC1>C^hH0L+|wRJo@0L)c(q`d`a;r0>uJ?a+Z?F2Ou(j*nQa@lWG{2RZ2$mA5(m EPYKVDV*mgE literal 0 HcmV?d00001 diff --git a/main.cpp b/main.cpp index 5d65f04..e9ceaf1 100644 --- a/main.cpp +++ b/main.cpp @@ -1,6 +1,5 @@ /* main.c */ /* Last Change: 2019/05/21 (Tue) 14:44:03. */ - #include"io.h" #include"solver.h" diff --git a/main.o b/main.o new file mode 100644 index 0000000000000000000000000000000000000000..ad7565f1510599a428700d562564608fd4c5af95 GIT binary patch literal 11296 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 class ap_fixed; +template class ap_ufixed; +template class ap_int; +template class ap_uint; + +//AP_INT +//-------------------------------------------------------- +template +class ap_int : public ap_private<_AP_W, true> { +#ifdef _MSC_VER +#pragma warning(disable: 4521 4522) +#endif /* #ifdef _MSC_VER */ +public: + typedef ap_private<_AP_W, true> Base; + + //Constructor + INLINE ap_int(): Base() {} + template + INLINE ap_int(const volatile ap_int<_AP_W2> &op):Base((const ap_private<_AP_W2,true> &)(op)) {} + + template + INLINE ap_int(const ap_int<_AP_W2> &op):Base((const ap_private<_AP_W2,true> &)(op)) {} + + template + INLINE ap_int(const ap_uint<_AP_W2> &op):Base((const ap_private<_AP_W2,false> &)(op)) {} + + template + INLINE ap_int(const volatile ap_uint<_AP_W2> &op):Base((const ap_private<_AP_W2,false> &)(op)) {} + + template + INLINE ap_int(const ap_range_ref<_AP_W2, _AP_S2>& ref):Base(ref) {} + + template + INLINE ap_int(const ap_bit_ref<_AP_W2, _AP_S2>& ref):Base(ref) {} + + template + INLINE ap_int(const ap_concat_ref<_AP_W2, _AP_T2, _AP_W3, _AP_T3>& ref):Base(ref) {} + + template + INLINE ap_int(const ap_fixed<_AP_W2, _AP_I2, _AP_Q2, _AP_O2, _AP_N2>& op) + :Base(op.to_ap_private()) {} + + template + INLINE ap_int(const ap_ufixed<_AP_W2, _AP_I2, _AP_Q2, _AP_O2, _AP_N2>& op) + :Base(op.to_ap_private()) {} + + template + INLINE ap_int(const volatile ap_fixed<_AP_W2, _AP_I2, _AP_Q2, _AP_O2, _AP_N2>& op) + :Base(op.to_ap_private()) {} + + template + INLINE ap_int(const volatile ap_ufixed<_AP_W2, _AP_I2, _AP_Q2, _AP_O2, _AP_N2>& op) + :Base(op.to_ap_private()) {} + + template + INLINE ap_int(const ap_private<_AP_W2, _AP_S2>& op):Base(op) {} + + template + INLINE ap_int(const af_bit_ref<_AP_W2, _AP_I2, _AP_S2, _AP_Q2, _AP_O2, + _AP_N2>& op):Base(op) {} + + template + INLINE ap_int(const af_range_ref<_AP_W2, _AP_I2, _AP_S2, _AP_Q2, _AP_O2, + _AP_N2>& op):Base(op) {} + + template + INLINE ap_int(const ap_fixed_base<_AP_W2, _AP_I2, _AP_S2, + _AP_Q2, _AP_O2, _AP_N2>& op):Base(op.to_ap_private()) {} + +#define CTOR(TYPE) \ + INLINE ap_int(TYPE v):Base(v) {} + CTOR(bool) + CTOR(signed char) + CTOR(unsigned char) + CTOR(short) + CTOR(unsigned short) + CTOR(int) + CTOR(unsigned int) + CTOR(long) + CTOR(unsigned long) + CTOR(unsigned long long) + CTOR(long long) + CTOR(float) + CTOR(double) + CTOR(const char*) + CTOR(const std::string&) +#undef CTOR + INLINE ap_int(const char* str, signed char rd):Base(str, rd) {} + //Assignment + //Another form of "write" + INLINE void operator = (const ap_int<_AP_W>& op2) volatile { + const_cast(this)->operator = (op2); + } + + INLINE void operator = (const volatile ap_int<_AP_W>& op2) volatile { + const_cast(this)->operator = (op2); + } + + INLINE ap_int<_AP_W>& operator = (const volatile ap_int<_AP_W>& op2) { + Base::operator = (const_cast& >(op2)); + return *this; + } + + INLINE ap_int<_AP_W>& operator = (const ap_int<_AP_W>& op2) { + Base::operator = ((const ap_private<_AP_W, true>&)op2); + return *this; + } +}; + +//AP_UINT +//--------------------------------------------------------------- +template +class ap_uint: public ap_private<_AP_W, false> { +#ifdef _MSC_VER +#pragma warning( disable : 4521 4522 ) +#endif +public: + typedef ap_private<_AP_W, false> Base; + //Constructor + INLINE ap_uint(): Base() {} + INLINE ap_uint(const ap_uint<_AP_W>& op) :Base(dynamic_cast&>(op)) {} + INLINE ap_uint(const volatile ap_uint<_AP_W>& op):Base(dynamic_cast&>(op)){} + template + INLINE ap_uint(const volatile ap_uint<_AP_W2> &op):Base((const ap_private<_AP_W2, false>&)(op)) {} + + template + INLINE ap_uint(const ap_uint<_AP_W2> &op) : Base((const ap_private<_AP_W2, false>&)(op)){} + + template + INLINE ap_uint(const ap_int<_AP_W2> &op) : Base((const ap_private<_AP_W2, true>&)(op)) {} + + template + INLINE ap_uint(const volatile ap_int<_AP_W2> &op) : Base((const ap_private<_AP_W2, false>&)(op)) {} + + template + INLINE ap_uint(const ap_range_ref<_AP_W2, _AP_S2>& ref):Base(ref) {} + + template + INLINE ap_uint(const ap_bit_ref<_AP_W2, _AP_S2>& ref):Base(ref) {} + + template + INLINE ap_uint(const ap_concat_ref<_AP_W2, _AP_T2, _AP_W3, _AP_T3>& ref):Base(ref) {} + + template + INLINE ap_uint(const ap_fixed<_AP_W2, _AP_I2, _AP_Q2, _AP_O2, _AP_N2>& op) + :Base(op.to_ap_private()) {} + + template + INLINE ap_uint(const ap_ufixed<_AP_W2, _AP_I2, _AP_Q2, _AP_O2, _AP_N2>& op) + :Base(op.to_ap_private()) {} + + template + INLINE ap_uint(const volatile ap_fixed<_AP_W2, _AP_I2, _AP_Q2, _AP_O2, _AP_N2>& op) + :Base(op.to_ap_private()) {} + + template + INLINE ap_uint(const volatile ap_ufixed<_AP_W2, _AP_I2, _AP_Q2, _AP_O2, _AP_N2>& op) + :Base(op) {} + + template + INLINE ap_uint(const ap_private<_AP_W2, _AP_S2>& op):Base(op) {} + + template + INLINE ap_uint(const af_bit_ref<_AP_W2, _AP_I2, _AP_S2, _AP_Q2, _AP_O2, + _AP_N2>& op):Base(op) {} + + template + INLINE ap_uint(const af_range_ref<_AP_W2, _AP_I2, _AP_S2, _AP_Q2, _AP_O2, + _AP_N2>& op):Base(op) {} + + template + INLINE ap_uint(const ap_fixed_base<_AP_W2, _AP_I2, _AP_S2, + _AP_Q2, _AP_O2, _AP_N2>& op):Base(op.to_ap_private()) {} + +#define CTOR(TYPE) \ + INLINE ap_uint(TYPE v):Base(v) {} + CTOR(bool) + CTOR(signed char) + CTOR(unsigned char) + CTOR(short) + CTOR(unsigned short) + CTOR(int) + CTOR(unsigned int) + CTOR(long) + CTOR(unsigned long) + CTOR(unsigned long long) + CTOR(long long) + CTOR(float) + CTOR(double) + CTOR(const char*) + CTOR(const std::string&) +#undef CTOR + INLINE ap_uint(const char* str, signed char rd):Base(str, rd) {} + //Assignment + //Another form of "write" + INLINE void operator = (const ap_uint<_AP_W>& op2) volatile { + Base::operator = (op2); + } + + INLINE void operator = (const volatile ap_uint<_AP_W>& op2) volatile { + Base::operator = (op2); + } + + INLINE ap_uint<_AP_W>& operator = (const volatile ap_uint<_AP_W>& op2) { + Base::operator = (op2); + return *this; + } + + INLINE ap_uint<_AP_W>& operator = (const ap_uint<_AP_W>& op2) { + Base::operator = ((const ap_private<_AP_W, false>&)(op2)); + return *this; + } +}; + +#define ap_bigint ap_int +#define ap_biguint ap_uint + +//AP_FIXED +//--------------------------------------------------------------------- +template +class ap_fixed: public ap_fixed_base<_AP_W, _AP_I, true, _AP_Q, _AP_O, _AP_N> { +#ifdef _MSC_VER +#pragma warning( disable : 4521 4522 ) +#endif +public: + typedef ap_fixed_base<_AP_W, _AP_I, true, _AP_Q, _AP_O, _AP_N> Base; + //Constructor + INLINE ap_fixed():Base() {} + + template + INLINE ap_fixed(const ap_fixed<_AP_W2, _AP_I2, _AP_Q2, _AP_O2, + _AP_N2>& op): Base(op) {} + + template + INLINE ap_fixed(const ap_ufixed<_AP_W2, _AP_I2, _AP_Q2, _AP_O2, + _AP_N2>& op): Base(ap_fixed_base<_AP_W2, _AP_I2, + false, _AP_Q2, _AP_O2, _AP_N2>(op)) {} + + template + INLINE ap_fixed(const ap_int<_AP_W2>& op): + Base(ap_private<_AP_W2, true>(op)) {} + + template + INLINE ap_fixed(const ap_uint<_AP_W2>& op):Base(ap_private<_AP_W2, false>(op)) {} + + template + INLINE ap_fixed(const volatile ap_fixed<_AP_W2, _AP_I2, _AP_Q2, _AP_O2, + _AP_N2>& op): Base(ap_fixed_base<_AP_W2, _AP_I2, + true, _AP_Q2, _AP_O2, _AP_N2>(op)) {} + + template + INLINE ap_fixed(const volatile ap_ufixed<_AP_W2, _AP_I2, _AP_Q2, _AP_O2, + _AP_N2>& op): Base(ap_fixed_base<_AP_W2, _AP_I2, + false, _AP_Q2, _AP_O2, _AP_N2>(op)) {} + + template + INLINE ap_fixed(const volatile ap_int<_AP_W2>& op): + Base(ap_private<_AP_W2, true>(op)) {} + + template + INLINE ap_fixed(const volatile ap_uint<_AP_W2>& op):Base(op) {} + + template + INLINE ap_fixed(const ap_fixed_base<_AP_W2, _AP_I2, _AP_S2, + _AP_Q2, _AP_O2, _AP_N2>& op):Base(op) {} + + template + INLINE ap_fixed(const ap_bit_ref<_AP_W2, _AP_S2>& op): + Base(op) {} + + template + INLINE ap_fixed(const ap_range_ref<_AP_W2, _AP_S2>& op): + Base(op) {} + + template + INLINE ap_fixed(const ap_concat_ref<_AP_W2, _AP_T2, _AP_W3, _AP_T3>& op): + Base(op) {} + + template + INLINE ap_fixed(const af_bit_ref<_AP_W2, _AP_I2, _AP_S2, + _AP_Q2, _AP_O2, _AP_N2>& op): Base(op) {} + + template + INLINE ap_fixed(const af_range_ref<_AP_W2, _AP_I2, _AP_S2, + _AP_Q2, _AP_O2, _AP_N2>& op): Base(op) {} + + template + INLINE ap_fixed(const ap_private<_AP_W2, _AP_S2>& op):Base(op) {} + + #define CTOR(TYPE) \ + INLINE ap_fixed(TYPE v):Base(v) {} + CTOR(bool) + CTOR(signed char) + CTOR(unsigned char) + CTOR(short) + CTOR(unsigned short) + CTOR(int) + CTOR(unsigned int) + CTOR(long) + CTOR(unsigned long) + CTOR(unsigned long long) + CTOR(long long) + CTOR(float) + CTOR(double) + CTOR(const char*) + CTOR(const std::string&) +#undef CTOR + INLINE ap_fixed(const char* str, signed char rd):Base(str, rd) {} + + //Assignment + INLINE ap_fixed& operator = (const ap_fixed<_AP_W, _AP_I, + _AP_Q, _AP_O, _AP_N>& op) { + Base::operator = (op); + return *this; + } + + INLINE ap_fixed& operator = (const volatile ap_fixed<_AP_W, _AP_I, + _AP_Q, _AP_O, _AP_N>& op) { + Base::operator = (op); + return *this; + } +}; + +//AP_ UFIXED +//--- ---------------------------------------------------------------- +template +class ap_ufixed : public ap_fixed_base<_AP_W, _AP_I, false, _AP_Q, _AP_O, _AP_N> { +#ifdef _MSC_VER +#pragma warning(disable: 4521 4522) +#endif /* #ifdef _MSC_VER */ +public: + typedef ap_fixed_base<_AP_W, _AP_I, false, _AP_Q, _AP_O, _AP_N> Base; + + //Constructor + INLINE ap_ufixed():Base() {} + + template + INLINE ap_ufixed(const ap_fixed<_AP_W2, _AP_I2, _AP_Q2, + _AP_O2, _AP_N2>& op) : Base(ap_fixed_base<_AP_W2, + _AP_I2, true, _AP_Q2, _AP_O2, _AP_N2>(op)) {} + + template + INLINE ap_ufixed(const ap_ufixed<_AP_W2, _AP_I2, _AP_Q2, + _AP_O2, _AP_N2>& op): Base(ap_fixed_base<_AP_W2, _AP_I2, + false, _AP_Q2, _AP_O2, _AP_N2>(op)) {} + + template + INLINE ap_ufixed(const ap_int<_AP_W2>& op): + Base((const ap_private<_AP_W2, true>&)(op)) {} + + template + INLINE ap_ufixed(const ap_uint<_AP_W2>& op): + Base((const ap_private<_AP_W2, false>&)(op)) {} + + template + INLINE ap_ufixed(const volatile ap_fixed<_AP_W2, _AP_I2, _AP_Q2, + _AP_O2, _AP_N2>& op) : Base(ap_fixed_base<_AP_W2, + _AP_I2, true, _AP_Q2, _AP_O2, _AP_N2>(op)) {} + + template + INLINE ap_ufixed(const volatile ap_ufixed<_AP_W2, _AP_I2, _AP_Q2, + _AP_O2, _AP_N2>& op): Base(ap_fixed_base<_AP_W2, _AP_I2, + false, _AP_Q2, _AP_O2, _AP_N2>(op)) {} + + template + INLINE ap_ufixed(const volatile ap_int<_AP_W2>& op): + Base(ap_private<_AP_W2, true>(op)) {} + + template + INLINE ap_ufixed(const volatile ap_uint<_AP_W2>& op): + Base(ap_private<_AP_W2, false>(op)) {} + + template + INLINE ap_ufixed(const ap_fixed_base<_AP_W2, _AP_I2, _AP_S2, _AP_Q2, + _AP_O2, _AP_N2>& op):Base(op) {} + + template + INLINE ap_ufixed(const ap_bit_ref<_AP_W2, _AP_S2>& op): + Base(op) {} + + template + INLINE ap_ufixed(const ap_range_ref<_AP_W2, _AP_S2>& op): + Base(op) {} + + template + INLINE ap_ufixed(const ap_concat_ref<_AP_W2, _AP_T2, _AP_W3, _AP_T3>& op): + Base(op) {} + + template + INLINE ap_ufixed(const af_bit_ref<_AP_W2, _AP_I2, _AP_S2, + _AP_Q2, _AP_O2, _AP_N2>& op): Base(op) {} + + template + INLINE ap_ufixed(const af_range_ref<_AP_W2, _AP_I2, _AP_S2, + _AP_Q2, _AP_O2, _AP_N2>& op): Base(op) {} + + template + INLINE ap_ufixed(const ap_private<_AP_W2, _AP_S2>& op):Base(op) {} + + #define CTOR(TYPE) \ + INLINE ap_ufixed(TYPE v):Base(v) {} + CTOR(bool) + CTOR(signed char) + CTOR(unsigned char) + CTOR(short) + CTOR(unsigned short) + CTOR(int) + CTOR(unsigned int) + CTOR(long) + CTOR(unsigned long) + CTOR(unsigned long long) + CTOR(long long) + CTOR(float) + CTOR(double) + CTOR(const char*) + CTOR(const std::string&) +#undef CTOR + INLINE ap_ufixed(const char* str, signed char rd):Base(str, rd) {} + + //Assignment + INLINE ap_ufixed& operator = (const ap_ufixed<_AP_W, _AP_I, + _AP_Q, _AP_O, _AP_N>& op) { + Base::operator = (op); + return *this; + } + + INLINE ap_ufixed& operator = (const volatile ap_ufixed<_AP_W, _AP_I, + _AP_Q, _AP_O, _AP_N>& op) { + Base::V = const_cast(op); + return *this; + } +}; + +#if defined(SYSTEMC_H) || defined(SYSTEMC_INCLUDED) +template +INLINE void sc_trace(sc_core::sc_trace_file *tf, const ap_int<_AP_W> &op, + const std::string &name) { + if (tf) + tf->trace(sc_dt::sc_lv<_AP_W>(op.to_string(2).c_str()), name); +} + +template +INLINE void sc_trace(sc_core::sc_trace_file *tf, const ap_uint<_AP_W> &op, + const std::string &name) { + if (tf) + tf->trace(sc_dt::sc_lv<_AP_W>(op.to_string(2).c_str()), name); +} + +template +INLINE void sc_trace(sc_core::sc_trace_file *tf, const ap_fixed<_AP_W, _AP_I, _AP_Q, _AP_O, _AP_N >&op, const std::string &name) { + tf->trace(sc_dt::sc_lv<_AP_W>(op.to_string(2).c_str()), name); +} + +template +INLINE void sc_trace(sc_core::sc_trace_file *tf, const ap_ufixed<_AP_W, _AP_I, _AP_Q, _AP_O, _AP_N >&op, const std::string &name) { + tf->trace(sc_dt::sc_lv<_AP_W>(op.to_string(2).c_str()), name); +} +#endif /* #if defined(SYSTEMC_H) || defined(SYSTEMC_INCLUDED) */ +#endif /* #ifndef __cplusplus */ +#endif /* #ifndef __AESL_AP_SIM_H__ */ \ No newline at end of file diff --git a/router/etc/ap_fixed_sim.h b/router/etc/ap_fixed_sim.h new file mode 100644 index 0000000..5be571d --- /dev/null +++ b/router/etc/ap_fixed_sim.h @@ -0,0 +1,2451 @@ +/* + * Copyright 2012 Xilinx, Inc. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef __AESL_GCC_AP_FIXED_H__ +#define __AESL_GCC_AP_FIXED_H__ + +#ifndef __cplusplus + #error C++ is required to include this header file +#endif /* #ifndef __cplusplus */ + + +#include +#ifndef __AESL_APDT_IN_SCFLOW__ + #include "etc/ap_int_sim.h" +#else + #include "../etc/ap_private.h" +#endif /* #ifndef __AESL_APDT_IN_SCFLOW__ */ + +#define FLOAT_MAN 23 +#define FLOAT_EXP 8 +#define DOUBLE_MAN 52 +#define DOUBLE_EXP 11 +// #define DOUBLE_MAN_MASK (~0ULL >> (64-DOUBLE_MAN-2)) +#define DOUBLE_MAN_MASK 0x3fffffffffffffULL +#define BIAS(e) ((1ULL<<(e-1))-1) +#define FLOAT_BIAS BIAS(FLOAT_EXP) +#define DOUBLE_BIAS BIAS(DOUBLE_EXP) + +/// Forward declaration. +template struct ap_fixed_base; + +///Proxy class, which allows bit selection to be used as both rvalue(for reading) and +//lvalue(for writing) +template +struct af_bit_ref { +#ifdef _MSC_VER + #pragma warning(disable: 4521 4522) +#endif /* #ifdef _MSC_VER */ + ap_fixed_base<_AP_W,_AP_I,_AP_S,_AP_Q,_AP_O, _AP_N>& d_bv; + int d_index; +public: + INLINE af_bit_ref(const af_bit_ref<_AP_W, _AP_I, _AP_S, + _AP_Q, _AP_O, _AP_N>& ref): + d_bv(ref.d_bv), d_index(ref.d_index) {} + + INLINE af_bit_ref(ap_fixed_base<_AP_W,_AP_I,_AP_S,_AP_Q,_AP_O, _AP_N>* bv, int index=0): + d_bv(*bv),d_index(index) {} + + INLINE operator bool() const { + return d_bv.V[d_index]; + } + + INLINE af_bit_ref& operator=(unsigned long long val) { + if (val) + d_bv.V.set(d_index); + else + d_bv.V.clear(d_index); + return *this; + } + + template + INLINE af_bit_ref& operator =(const ap_private<_AP_W2,_AP_S2>& val) { + return operator=(val!=0); + } + + INLINE af_bit_ref& operator =(const af_bit_ref<_AP_W, _AP_I, _AP_S, + _AP_Q, _AP_O, _AP_N>& val) { + return operator=((unsigned long long)(bool)val); + } + + template + INLINE af_bit_ref operator=(const af_bit_ref<_AP_W2,_AP_I2,_AP_S2,_AP_Q2,_AP_O2, _AP_N2>& val) { + return operator=((unsigned long long)(bool)val); + } + + template + INLINE af_bit_ref& operator = ( const ap_bit_ref<_AP_W2, _AP_S2> &val) { + return operator =((unsigned long long) (bool) val); + } + + template + INLINE af_bit_ref& operator = ( const ap_range_ref<_AP_W2,_AP_S2>& val) { + return operator =((const ap_private<_AP_W2, false>) val); + } + + template + INLINE af_bit_ref& operator= (const af_range_ref<_AP_W2, _AP_I2, _AP_S2, + _AP_Q2, _AP_O2, _AP_N2>& val) { + return operator=((const ap_private<_AP_W2, false>)(val)); + } + + template + INLINE af_bit_ref& operator= (const ap_concat_ref<_AP_W2, _AP_T3, _AP_W3, _AP_T3>& val) { + return operator=((const ap_private<_AP_W2 + _AP_W3, false>)(val)); + } + + template + INLINE ap_concat_ref<1, af_bit_ref, _AP_W2, ap_private<_AP_W2, _AP_S2> > + operator, (ap_private<_AP_W2, _AP_S2>& op) { + return ap_concat_ref<1, af_bit_ref, _AP_W2, + ap_private<_AP_W2, _AP_S2> >(*this, op); + } + + template + INLINE ap_concat_ref<1, af_bit_ref, 1, ap_bit_ref<_AP_W2, _AP_S2> > + operator, (const ap_bit_ref<_AP_W2, _AP_S2> &op) { + return ap_concat_ref<1, af_bit_ref, 1, + ap_bit_ref<_AP_W2, _AP_S2> >(*this, + const_cast& >(op)); + } + + template + INLINE ap_concat_ref<1, af_bit_ref, _AP_W2, ap_range_ref<_AP_W2, _AP_S2> > + operator, (const ap_range_ref<_AP_W2, _AP_S2> &op) { + return ap_concat_ref<1, af_bit_ref, _AP_W2, + ap_range_ref<_AP_W2, _AP_S2> >(*this, + const_cast& >(op)); + } + + template + INLINE ap_concat_ref<1, af_bit_ref, _AP_W2 + _AP_W3, + ap_concat_ref<_AP_W2, _AP_T2, _AP_W3, _AP_T3> > + operator, (const ap_concat_ref<_AP_W2, _AP_T2, _AP_W3, _AP_T3> &op) { + return ap_concat_ref<1, af_bit_ref, _AP_W2 + _AP_W3, + ap_concat_ref<_AP_W2, _AP_T2, _AP_W3, _AP_T3> >(*this, + const_cast& >(op)); + } + + template + INLINE ap_concat_ref<1, af_bit_ref, _AP_W2, + af_range_ref<_AP_W2, _AP_I2, _AP_S2, _AP_Q2, _AP_O2, _AP_N2> > + operator, (const af_range_ref<_AP_W2, _AP_I2, _AP_S2, _AP_Q2, + _AP_O2, _AP_N2> &op) { + return ap_concat_ref<1, af_bit_ref, _AP_W2, + af_range_ref<_AP_W2, _AP_I2, _AP_S2, _AP_Q2, _AP_O2, + _AP_N2> >(*this, const_cast& >(op)); + } + + template + INLINE ap_concat_ref<1, af_bit_ref, 1, + af_bit_ref<_AP_W2, _AP_I2, _AP_S2, _AP_Q2, _AP_O2, _AP_N2> > + operator, (const af_bit_ref<_AP_W2, _AP_I2, _AP_S2, _AP_Q2, + _AP_O2, _AP_N2> &op) { + return ap_concat_ref<1, af_bit_ref, 1, + af_bit_ref<_AP_W2, _AP_I2, _AP_S2, _AP_Q2, _AP_O2, _AP_N2> >(*this, + const_cast& >(op)); + } + + template + INLINE bool operator == (const af_bit_ref<_AP_W2, _AP_I2, + _AP_S2, _AP_Q2, _AP_O2, _AP_N2>& op) { + return get() == op.get(); + } + + template + INLINE bool operator != (const af_bit_ref<_AP_W2, _AP_I2, + _AP_S2, _AP_Q2, _AP_O2, _AP_N2>& op) { + return get() != op.get(); + } + + INLINE bool operator ~ () const { + bool bit = (d_bv.V)[d_index]; + return bit ? false : true; + } + + INLINE int length() const { + return 1; + } + + INLINE bool get() { + return d_bv.V[d_index]; + } + + INLINE bool get() const { + return d_bv.V[d_index]; + } + + INLINE std::string to_string() const { + return d_bv.V[d_index] ? "1" : "0"; + } +}; + +///Range(slice) reference +//------------------------------------------------------------ +template +struct af_range_ref { +#ifdef _MSC_VER + #pragma warning(disable: 4521 4522) +#endif /* #ifdef _MSC_VER */ + ap_fixed_base<_AP_W, _AP_I, _AP_S, _AP_Q, _AP_O, _AP_N> &d_bv; + int l_index; + int h_index; + +public: + INLINE af_range_ref(const af_range_ref<_AP_W, _AP_I, _AP_S, + _AP_Q, _AP_O, _AP_N>& ref): + d_bv(ref.d_bv), l_index(ref.l_index), h_index(ref.h_index) {} + + INLINE af_range_ref(ap_fixed_base<_AP_W, _AP_I, _AP_S, _AP_Q, _AP_O, _AP_N>* bv, int h, int l): + d_bv(*bv),l_index(l),h_index(h) { + //if (h < l) + // fprintf(stderr, + //"Warning! The bits selected will be returned in reverse order\n"); + } + + INLINE operator ap_private<_AP_W, false> () const { + if (h_index >= l_index) { + ap_private<_AP_W, false> val(d_bv.V); + ap_private<_AP_W,false> mask(-1); + mask>>=_AP_W-(h_index-l_index+1); + val>>=l_index; + return val&=mask; + } else { + ap_private<_AP_W, false> val = 0; + for (int i=0, j=l_index;j>=0&&j>=h_index;j--,i++) + if ((d_bv.V)[j]) val.set(i); + return val; + } + } + + INLINE operator unsigned long long() const { + return get().to_uint64(); + } + + template + INLINE af_range_ref& operator =(const ap_private<_AP_W2,_AP_S2>& val) { + ap_private<_AP_W, false> vval= ap_private<_AP_W, false>(val); + if (l_index > h_index) { + for (int i=0, j=l_index;j>=0&&j>=h_index;j--,i++) + vval[i]? d_bv.V.set(j):d_bv.V.clear(j); + } else { + ap_private<_AP_W,false> mask(-1); + if (l_index>0) { + mask<<=l_index; + vval<<=l_index; + } + if (h_index<_AP_W-1) { + ap_private<_AP_W,false> mask2(-1); + mask2>>=_AP_W-h_index-1; + mask&=mask2; + vval&=mask2; + } + mask.flip(); + d_bv.V &= mask; + d_bv.V |= vval; + } + return *this; + } + + INLINE af_range_ref& operator = (unsigned long long val) { + const ap_private<_AP_W, false> tmpVal(val); + return operator = (tmpVal); + } + + template + INLINE af_range_ref& operator = + (const ap_concat_ref <_AP_W3, _AP_T3, _AP_W4, _AP_T4>& val) { + const ap_private<_AP_W, false> tmpVal(val); + return operator = (tmpVal); + } + + template + INLINE af_range_ref& operator =(const ap_bit_ref<_AP_W3, _AP_S3>& val) { + const ap_private<_AP_W, false> tmpVal(val); + return operator = (tmpVal); + } + + template + INLINE af_range_ref& operator =(const ap_range_ref<_AP_W3,_AP_S3>& val) { + const ap_private<_AP_W, false> tmpVal(val); + return operator =(tmpVal); + } + + template + INLINE af_range_ref& operator= (const af_range_ref<_AP_W2, _AP_I2, _AP_S2, _AP_Q2, _AP_O2, _AP_N2>& val) { + const ap_private<_AP_W2, false> tmp= val.get(); + return operator = (tmp); + } + + INLINE af_range_ref& operator= (const af_range_ref<_AP_W, _AP_I, _AP_S, + _AP_Q, _AP_O, _AP_N>& val) { + const ap_private<_AP_W, false> tmp= val.get(); + return operator = (tmp); + } + + template + INLINE af_range_ref& operator= (const ap_fixed_base<_AP_W2, + _AP_I2, _AP_S2, _AP_Q2, _AP_O2, _AP_N2>& val) { + return operator=(val.to_ap_private()); + } + + template + INLINE bool operator == (const ap_range_ref<_AP_W2, _AP_S2>& op2) { + ap_private<_AP_W,false> lhs=get(); + ap_private<_AP_W2,false> rhs=op2.get(); + return lhs==rhs; + } + + template + INLINE bool operator != (const ap_range_ref<_AP_W2, _AP_S2>& op2) { + ap_private<_AP_W,false> lhs=get(); + ap_private<_AP_W2,false> rhs=op2.get(); + return lhs!=rhs; + } + + template + INLINE bool operator > (const ap_range_ref<_AP_W2, _AP_S2>& op2) { + ap_private<_AP_W,false> lhs=get(); + ap_private<_AP_W2,false> rhs=op2.get(); + return lhs>rhs; + } + + template + INLINE bool operator >= (const ap_range_ref<_AP_W2, _AP_S2>& op2) { + ap_private<_AP_W,false> lhs=get(); + ap_private<_AP_W2,false> rhs=op2.get(); + return lhs>=rhs; + } + + template + INLINE bool operator < (const ap_range_ref<_AP_W2, _AP_S2>& op2) { + ap_private<_AP_W,false> lhs=get(); + ap_private<_AP_W2,false> rhs=op2.get(); + return lhs + INLINE bool operator <= (const ap_range_ref<_AP_W2, _AP_S2>& op2) { + ap_private<_AP_W,false> lhs=get(); + ap_private<_AP_W2,false> rhs=op2.get(); + return lhs<=rhs; + } + + template + INLINE bool operator == (const af_range_ref<_AP_W2, _AP_I2, _AP_S2, _AP_Q2, _AP_O2, _AP_N2>& op2) { + ap_private<_AP_W,false> lhs=get(); + ap_private<_AP_W2,false> rhs=op2.get(); + return lhs==rhs; + } + + template + INLINE bool operator != (const af_range_ref<_AP_W2, _AP_I2, _AP_S2, _AP_Q2, _AP_O2, _AP_N2>& op2) { + ap_private<_AP_W,false> lhs=get(); + ap_private<_AP_W2,false> rhs=op2.get(); + return lhs!=rhs; + } + + template + INLINE bool operator > (const af_range_ref<_AP_W2, _AP_I2, _AP_S2, _AP_Q2, _AP_O2, _AP_N2>& op2) { + ap_private<_AP_W,false> lhs=get(); + ap_private<_AP_W2,false> rhs=op2.get(); + return lhs>rhs; + } + + template + INLINE bool operator >= (const af_range_ref<_AP_W2, _AP_I2, _AP_S2, _AP_Q2, _AP_O2, _AP_N2>& op2) { + ap_private<_AP_W,false> lhs=get(); + ap_private<_AP_W2,false> rhs=op2.get(); + return lhs>=rhs; + } + + template + INLINE bool operator < (const af_range_ref<_AP_W2, _AP_I2, _AP_S2, _AP_Q2, _AP_O2, _AP_N2>& op2) { + ap_private<_AP_W,false> lhs=get(); + ap_private<_AP_W2,false> rhs=op2.get(); + return lhs + INLINE bool operator <= (const af_range_ref<_AP_W2, _AP_I2, _AP_S2, _AP_Q2, _AP_O2, _AP_N2>& op2) { + ap_private<_AP_W,false> lhs=get(); + ap_private<_AP_W2,false> rhs=op2.get(); + return lhs<=rhs; + } + + template + INLINE void set(const ap_private<_AP_W2,false>& val) { + ap_private<_AP_W,_AP_S> vval=val; + if (l_index>h_index) { + for (int i=0, j=l_index;j>=0&&j>=h_index;j--,i++) + vval[i]? d_bv.V.set(j):d_bv.V.clear(j); + } else { + ap_private<_AP_W,_AP_S> mask(-1); + if (l_index>0) { + ap_private<_AP_W,false> mask1(-1); + mask1>>=_AP_W-l_index; + mask1.flip(); + mask=mask1; + //vval&=mask1; + vval<<=l_index; + } + if (h_index<_AP_W-1) { + ap_private<_AP_W,false> mask2(-1); + mask2<<=h_index+1; + mask2.flip(); + mask&=mask2; + vval&=mask2; + } + mask.flip(); + d_bv&=mask; + d_bv|=vval; + } + + } + + INLINE ap_private<_AP_W,false> get() const { + if (h_index val(0); + for (int i=0, j=l_index;j>=0&&j>=h_index;j--,i++) + if ((d_bv.V)[j]) val.set(i); + return val; + } else { + ap_private<_AP_W, false> val = ap_private<_AP_W,false>(d_bv.V); + val>>= l_index; + if (h_index<_AP_W-1) + { + ap_private<_AP_W,false> mask(-1); + mask>>=_AP_W-(h_index-l_index+1); + val&=mask; + } + return val; + } + } + + template + INLINE ap_concat_ref<_AP_W, af_range_ref, _AP_W2, ap_private<_AP_W2, _AP_S2> > + operator, (ap_private<_AP_W2, _AP_S2>& op) { + return ap_concat_ref<_AP_W, af_range_ref, _AP_W2, + ap_private<_AP_W2, _AP_S2> >(*this, op); + } + + template + INLINE ap_concat_ref<_AP_W, af_range_ref, 1, ap_bit_ref<_AP_W2, _AP_S2> > + operator, (const ap_bit_ref<_AP_W2, _AP_S2> &op) { + return ap_concat_ref<_AP_W, af_range_ref, 1, + ap_bit_ref<_AP_W2, _AP_S2> >(*this, + const_cast& >(op)); + } + + template + INLINE ap_concat_ref<_AP_W, af_range_ref, _AP_W2, ap_range_ref<_AP_W2, _AP_S2> > + operator, (const ap_range_ref<_AP_W2, _AP_S2> &op) { + return ap_concat_ref<_AP_W, af_range_ref, _AP_W2, + ap_range_ref<_AP_W2, _AP_S2> >(*this, + const_cast& >(op)); + } + + template + INLINE ap_concat_ref<_AP_W, af_range_ref, _AP_W2 + _AP_W3, + ap_concat_ref<_AP_W2, _AP_T2, _AP_W3, _AP_T3> > + operator, (const ap_concat_ref<_AP_W2, _AP_T2, _AP_W3, _AP_T3> &op) { + return ap_concat_ref<_AP_W, af_range_ref, _AP_W2 + _AP_W3, + ap_concat_ref<_AP_W2, _AP_T2, _AP_W3, _AP_T3> >(*this, + const_cast& >(op)); + } + + template + INLINE ap_concat_ref<_AP_W, af_range_ref, _AP_W2, + af_range_ref<_AP_W2, _AP_I2, _AP_S2, _AP_Q2, _AP_O2, _AP_N2> > + operator, (const af_range_ref<_AP_W2, _AP_I2, _AP_S2, _AP_Q2, + _AP_O2, _AP_N2> &op) { + return ap_concat_ref<_AP_W, af_range_ref, _AP_W2, + af_range_ref<_AP_W2, _AP_I2, _AP_S2, _AP_Q2, _AP_O2, _AP_N2> >(*this, + const_cast& > (op)); + } + + template + INLINE ap_concat_ref<_AP_W, af_range_ref, 1, + af_bit_ref<_AP_W2, _AP_I2, _AP_S2, _AP_Q2, _AP_O2, _AP_N2> > + operator, (const af_bit_ref<_AP_W2, _AP_I2, _AP_S2, _AP_Q2, + _AP_O2, _AP_N2> &op) { + return ap_concat_ref<_AP_W, af_range_ref, 1, + af_bit_ref<_AP_W2, _AP_I2, _AP_S2, _AP_Q2, _AP_O2, _AP_N2> >(*this, + const_cast& >(op)); + } + + INLINE int length() const { + return h_index>=l_index?h_index-l_index+1:l_index-h_index+1; + } + + INLINE int to_int() const { + ap_private<_AP_W,false> val=get(); + return val.to_int(); + } + + INLINE unsigned int to_uint() const { + ap_private<_AP_W,false> val=get(); + return val.to_uint(); + } + + INLINE long to_long() const { + ap_private<_AP_W,false> val=get(); + return val.to_long(); + } + + INLINE unsigned long to_ulong() const { + ap_private<_AP_W,false> val=get(); + return val.to_ulong(); + } + + INLINE ap_slong to_int64() const { + ap_private<_AP_W,false> val=get(); + return val.to_int64(); + } + + INLINE ap_ulong to_uint64() const { + ap_private<_AP_W,false> val=get(); + return val.to_uint64(); + } + + INLINE std::string to_string(uint8_t radix) const { + return get().to_string(radix); + } + +}; + +//----------------------------------------------------------------------------- +///ap_fixed_base: AutoPilot fixed point +//----------------------------------------------------------------------------- +template +struct ap_fixed_base { +#ifdef _MSC_VER + #pragma warning(disable: 4521 4522) +#endif /* #ifdef _MSC_VER */ +public: + template friend struct +ap_fixed_base; + template friend struct +af_bit_ref; + + INLINE void overflow_adjust(bool underflow, bool overflow, + bool lD, bool sign) { + if (!overflow && !underflow) return; + switch (_AP_O) { + case AP_WRAP: + if (_AP_N == 0) + return; + if (_AP_S) { + //signed SC_WRAP + //n_bits == 1; + if (_AP_N > 1) { + ap_private<_AP_W, _AP_S> mask(-1); + if (_AP_N >= _AP_W) mask = 0; + else mask.lshr(_AP_N); + if (sign) + V &= mask; + else + V |= ~mask; + } + sign ? V.set(_AP_W - 1) : V.clear(_AP_W - 1); + } else { + //unsigned SC_WRAP + ap_private<_AP_W, _AP_S> mask(-1); + if (_AP_N >= _AP_W) mask = 0; + else mask.lshr(_AP_N); + mask.flip(); + V |= mask; + } + break; + case AP_SAT_ZERO: + V.clear(); + break; + case AP_WRAP_SM: + { + bool Ro = ap_private_ops::get<_AP_W, _AP_S, _AP_W -1>(V); // V[_AP_W -1]; + if (_AP_N == 0) { + if (lD != Ro) { + V.flip(); + lD ? ap_private_ops::set<_AP_W, _AP_S, _AP_W - 1>(V) : + ap_private_ops::clear<_AP_W, _AP_S, _AP_W - 1>(V); + } + } else { + if (_AP_N == 1 && sign != Ro) { + V.flip(); + } else if (_AP_N > 1) { + bool lNo = ap_private_ops::get<_AP_W, _AP_S, _AP_W - _AP_N> (V); // V[_AP_W - _AP_N]; + if (lNo == sign) + V.flip(); + ap_private<_AP_W, false> mask(-1); + if (_AP_N >= _AP_W) mask = 0; + else mask.lshr(_AP_N); + if (sign) + V &= mask; + else + V |= mask.flip(); + sign ? ap_private_ops::set<_AP_W, _AP_S, _AP_W - 1>(V) : ap_private_ops::clear<_AP_W, _AP_S, _AP_W - 1>(V); + } + } + } + break; + default: + if (_AP_S) { + if (overflow) { + V.set(); ap_private_ops::clear<_AP_W, _AP_S, _AP_W-1>(V); + } else if (underflow) { + V.clear(); + ap_private_ops::set<_AP_W, _AP_S, _AP_W-1>(V); + if (_AP_O == AP_SAT_SYM) + ap_private_ops::set<_AP_W, _AP_S, 0>(V); + } + } else { + if (overflow) + V.set(); + else if (underflow) + V.clear(); + } + } + } + + INLINE bool quantization_adjust(bool qb, bool r, bool s) { + bool carry=ap_private_ops::get<_AP_W, _AP_S, _AP_W-1>(V); + switch (_AP_Q) { + case AP_TRN: + return false; + case AP_RND_ZERO: + qb &= s || r; + break; + case AP_RND_MIN_INF: + qb &= r; + break; + case AP_RND_INF: + qb &= !s || r; + break; + case AP_RND_CONV: + qb &= ap_private_ops::get<_AP_W, _AP_S, 0>(V) || r; + break; + case AP_TRN_ZERO: + qb = s && ( qb || r ); + break; + default:; + + } + if (qb) ++V; + //only when old V[_AP_W-1]==1 && new V[_AP_W-1]==0 + return carry && !(ap_private_ops::get<_AP_W, _AP_S, _AP_W-1>(V)); //(!V[_AP_W-1]); + } + + template + struct RType { + enum { + _AP_F=_AP_W-_AP_I, + F2=_AP_W2-_AP_I2, + mult_w = _AP_W+_AP_W2, + mult_i = _AP_I+_AP_I2, + mult_s = _AP_S||_AP_S2, + plus_w = AP_MAX(_AP_I+(_AP_S2&&!_AP_S),_AP_I2+(_AP_S&&!_AP_S2))+1+AP_MAX(_AP_F,F2), + plus_i = AP_MAX(_AP_I+(_AP_S2&&!_AP_S),_AP_I2+(_AP_S&&!_AP_S2))+1, + plus_s = _AP_S||_AP_S2, + minus_w = AP_MAX(_AP_I+(_AP_S2&&!_AP_S),_AP_I2+(_AP_S&&!_AP_S2))+1+AP_MAX(_AP_F,F2), + minus_i = AP_MAX(_AP_I+(_AP_S2&&!_AP_S),_AP_I2+(_AP_S&&!_AP_S2))+1, + minus_s = true, +#ifndef __SC_COMPATIBLE__ + div_w = _AP_W + AP_MAX(_AP_W2 - _AP_I2, 0) + _AP_S2, +#else + div_w = _AP_W + AP_MAX(_AP_W2 - _AP_I2, 0) + _AP_S2 + AP_MAX(_AP_I2, 0), +#endif /* #ifndef __SC_COMPATIBLE__ */ + div_i = _AP_I + (_AP_W2-_AP_I2) + _AP_S2, + div_s = _AP_S||_AP_S2, + logic_w = AP_MAX(_AP_I+(_AP_S2&&!_AP_S),_AP_I2+(_AP_S&&!_AP_S2))+AP_MAX(_AP_F,F2), + logic_i = AP_MAX(_AP_I+(_AP_S2&&!_AP_S),_AP_I2+(_AP_S&&!_AP_S2)), + logic_s = _AP_S||_AP_S2 + }; + + typedef ap_fixed_base mult; + typedef ap_fixed_base plus; + typedef ap_fixed_base minus; + typedef ap_fixed_base logic; + typedef ap_fixed_base div; + typedef ap_fixed_base<_AP_W, _AP_I, _AP_S> arg1; + }; + INLINE void report() { +#if 0 + if (_AP_W > 1024 && _AP_W <= 4096) { + fprintf(stderr, "[W] W=%d is out of bound (1<=W<=1024):" + " for synthesis, please define macro AP_INT_TYPE_EXT(N) to" + " extend the valid range.\n", _AP_W); + } else +#endif /* #if 0 */ + if (_AP_W > MAX_MODE(AP_INT_MAX_W) * 1024) { + fprintf(stderr, "[E] ap_%sfixed<%d, ...>: Bitwidth exceeds the " + "default max value %d. Please use macro " + "AP_INT_MAX_W to set a larger max value.\n", + _AP_S?"":"u", _AP_W, + MAX_MODE(AP_INT_MAX_W) * 1024); + exit(1); + } + } + + /// Constructors. + // ------------------------------------------------------------------------- +#if 0 + #ifdef __SC_COMPATIBLE__ + INLINE ap_fixed_base():V(uint32_t(_AP_W), uint64_t(0)) {} + #else + INLINE ap_fixed_base():V(uint32_t(_AP_W)) {} + #endif /* #ifdef __SC_COMPATIBLE__ */ +#else + INLINE ap_fixed_base():V(0) {} +#endif /* #if 0 */ + // INLINE ap_fixed_base():V() {} + // INLINE explicit ap_fixed_base(const ap_private<_AP_W+_AP_I, _AP_S>& _V):V(_V) {} + INLINE ap_fixed_base(const ap_fixed_base& op):V(op.V) {} + template + INLINE ap_fixed_base(const ap_fixed_base<_AP_W2,_AP_I2,_AP_S2,_AP_Q2,_AP_O2, _AP_N2>& op):V(0) { + enum {N2=_AP_W2,_AP_F=_AP_W-_AP_I,F2=_AP_W2-_AP_I2,QUAN_INC=F2>_AP_F && !(_AP_Q==AP_TRN || + (_AP_Q==AP_TRN_ZERO && !_AP_S2))}; + if (!op) return; + bool carry=false; + //handle quantization + enum { sh_amt =(F2>_AP_F)?F2-_AP_F:_AP_F-F2}; + const ap_private<_AP_W2, _AP_S2>& val = op.V; + bool neg_src=val.isNegative(); + if (F2==_AP_F) + V=val; + + else if (F2>_AP_F) { + if (sh_amt >= _AP_W2) + V = neg_src ? -1 : 0; + else + V = _AP_S2?val.ashr(sh_amt):val.lshr(sh_amt); + if (_AP_Q!=AP_TRN && !(_AP_Q==AP_TRN_ZERO && !_AP_S2)) { + bool qb = false; + if (F2-_AP_F>_AP_W2) + qb = neg_src; + else + qb = ap_private_ops::get<_AP_W2, _AP_S2, F2-_AP_F-1>(val); + + bool r=false; + enum { pos3 = F2-_AP_F-2}; + if (pos3>=_AP_W2-1) + r=val!=0; + else if (pos3>=0) + r = (val<<(_AP_W2-1-pos3))!=0; + carry = quantization_adjust(qb,r,neg_src); + } + } else { //no quantization + if (sh_amt < _AP_W) { + V=val; + V <<= sh_amt; + } + } + //hanle overflow/underflow + if ((_AP_O!=AP_WRAP || _AP_N != 0) && + ((!_AP_S && _AP_S2) || _AP_I-_AP_S < + _AP_I2 - _AP_S2 + (QUAN_INC|| (_AP_S2 && + _AP_O==AP_SAT_SYM)))) {//saturation + bool deleted_zeros = _AP_S2?true:!carry, + deleted_ones = true; + bool lD=(_AP_I2>_AP_I && _AP_W2-_AP_I2+_AP_I>=0) && + ap_private_ops::get<_AP_W2, _AP_S2, _AP_W2-_AP_I2+_AP_I>(val); + enum { pos1=F2-_AP_F+_AP_W, pos2=F2-_AP_F+_AP_W+1}; + if (pos1 < _AP_W2) { + bool Range1_all_ones= true; + bool Range1_all_zeros= true; + if (pos1 >= 0) { + enum { __W = (_AP_W2-pos1) > 0 ? (_AP_W2-pos1) : 1 }; + const ap_private<__W, _AP_S2> Range1=ap_private<__W, _AP_S2>(val.lshr(pos1)); + Range1_all_ones=Range1.isAllOnesValue(); + Range1_all_zeros=Range1.isMinValue(); + } else { + Range1_all_ones=false; + Range1_all_zeros=val.isMinValue(); + } + bool Range2_all_ones=true; + if (pos2<_AP_W2 && pos2>=0) { + enum { __W = (_AP_W2-pos2)>0 ? (_AP_W2-pos2) : 1}; + ap_private<__W, true> Range2=ap_private<__W, true>(val.lshr(pos2)); + Range2_all_ones=Range2.isAllOnesValue(); + } else if (pos2<0) + Range2_all_ones=false; + + deleted_zeros=deleted_zeros && (carry?Range1_all_ones:Range1_all_zeros); + deleted_ones=carry?Range2_all_ones&&(F2-_AP_F+_AP_W<0||!lD) + :Range1_all_ones; + neg_src= neg_src&&!(carry && Range1_all_ones); + } else + neg_src = neg_src && V[_AP_W-1]; + + bool neg_trg= V.isNegative(); + bool overflow=(neg_trg||!deleted_zeros) && !val.isNegative(); + bool underflow=(!neg_trg||!deleted_ones)&&neg_src; + //printf("neg_src = %d, neg_trg = %d, deleted_zeros = %d, + // deleted_ones = %d, overflow = %d, underflow = %d\n", + // neg_src, neg_trg, deleted_zeros, deleted_ones, + // overflow, underflow); + if (_AP_O==AP_SAT_SYM && _AP_S2 && _AP_S) + underflow |= neg_src && (_AP_W>1?V.isMinSignedValue():true); + overflow_adjust(underflow, overflow, lD, neg_src); + } + report(); + } + + template + INLINE ap_fixed_base(const volatile ap_fixed_base<_AP_W2,_AP_I2, + _AP_S2,_AP_Q2,_AP_O2, _AP_N2> &op) : V(op.V) { + *this = const_cast&>(op); + } + + template + INLINE ap_fixed_base(const ap_private<_AP_W2,_AP_S2>& op) { + ap_fixed_base<_AP_W2,_AP_W2,_AP_S2> f_op; + f_op.V=op; + *this = f_op; + } + + INLINE ap_fixed_base(bool b) { + *this=(ap_private<1,false>)b; + report(); + } + + INLINE ap_fixed_base(char b) { + *this=(ap_private<8,false>)b; + report(); + } + + INLINE ap_fixed_base(signed char b) { + *this=(ap_private<8,true>)b; + report(); + } + + INLINE ap_fixed_base(unsigned char b) { + *this=(ap_private<8,false>)b; + report(); + } + + INLINE ap_fixed_base(signed short b) { + *this=(ap_private<16,true>)b; + report(); + } + + INLINE ap_fixed_base(unsigned short b) { + *this=(ap_private<16,false>)b; + report(); + } + + INLINE ap_fixed_base(signed int b) { + *this=(ap_private<32,true>)b; + report(); + } + + INLINE ap_fixed_base(unsigned int b) { + *this=(ap_private<32,false>)b; + report(); + } +# if defined __x86_64__ + INLINE ap_fixed_base(signed long b) { + *this=(ap_private<64,true>)b; + report(); + } + + INLINE ap_fixed_base(unsigned long b) { + *this=(ap_private<64,false>)b; + report(); + } +# else + INLINE ap_fixed_base(signed long b) { + *this=(ap_private<32,true>)b; + report(); + } + + INLINE ap_fixed_base(unsigned long b) { + *this=(ap_private<32,false>)b; + report(); + } +# endif + + INLINE ap_fixed_base(ap_slong b) { + *this=(ap_private<64,true>)b; + report(); + } + + INLINE ap_fixed_base(ap_ulong b) { + *this=(ap_private<64,false>)b; + report(); + } + +#if 1 + INLINE ap_fixed_base(const char* val):V(0) { + ap_private<_AP_W, _AP_S> Tmp(val); + V = Tmp; + } + + INLINE ap_fixed_base(const char* val, signed char rd): V(0) { + ap_private<_AP_W, _AP_S> Tmp(val, rd); + V = Tmp; + } + +#endif + + INLINE ap_fixed_base(const std::string& val) { + ap_private<_AP_W, _AP_S> Tmp(val, 2); + V = Tmp; + report(); + } + + template + INLINE ap_fixed_base(const ap_bit_ref<_AP_W2, _AP_S2>& op) { + *this = ((bool)op); + report(); + } + + template + INLINE ap_fixed_base(const ap_range_ref<_AP_W2, _AP_S2>& op) { + *this = ap_private<_AP_W2, _AP_S2>(op); + report(); + } + + template + INLINE ap_fixed_base(const ap_concat_ref<_AP_W2, _AP_T2, _AP_W3, _AP_T3>& op) { + *this = ((const ap_private<_AP_W2 + _AP_W3, false>&)(op)); + report(); + } + + template + INLINE ap_fixed_base(const af_bit_ref<_AP_W2, _AP_I2, _AP_S2, _AP_Q2, _AP_O2, _AP_N2>& op) { + *this = (bool(op)); + report(); + } + + template + INLINE ap_fixed_base(const af_range_ref<_AP_W2, _AP_I2, _AP_S2, _AP_Q2, _AP_O2, _AP_N2>& op) { + *this = (ap_private<_AP_W2, false>(op)); + report(); + } + + //helper function + INLINE unsigned long long doubleToRawBits(double pf)const { + union { + unsigned long long __L; + double __D; + }LD; + LD.__D=pf; + return LD.__L; + } + + + INLINE double rawBitsToDouble(unsigned long long pi) const { + union { + unsigned long long __L; + double __D; + }LD; + LD.__L=pi; + return LD.__D; + } + + INLINE float rawBitsToFloat(uint32_t pi) const { + union { + uint32_t __L; + float __D; + }LD; + LD.__L = pi; + return LD.__D; + } + + INLINE ap_fixed_base(double d):V(0) { + if (!d) return; + const bool isneg=d<0; + + const uint64_t ireg=doubleToRawBits(isneg?-d:d); + if ((ireg&0x7fffffffffffffffULL)!=0) { + const int32_t exp=(((ireg)>>DOUBLE_MAN)&0x07ff)-DOUBLE_BIAS; + ap_private man = ireg & DOUBLE_MAN_MASK; + man.clear(DOUBLE_MAN+1); + man.set(DOUBLE_MAN); + if (isneg) { + man.flip(); + man++; + } + + enum {_AP_S2=true, _AP_W2=DOUBLE_MAN+2,_AP_F=_AP_W -_AP_I }; + const int _AP_I2=exp+2; + const int F2=_AP_W2-_AP_I2; + const bool QUAN_INC=F2>_AP_F && !(_AP_Q==AP_TRN || (_AP_Q==AP_TRN_ZERO && + !_AP_S2)); + bool carry=false; + //handle quantization + const unsigned sh_amt=abs(F2-_AP_F); // sh_amt = F2>_AP_F ? F2 -_AP_F : _AP_F-F2; + if (F2==_AP_F ) + V=man; + else if (F2>_AP_F) { + if (sh_amt >= DOUBLE_MAN+2) + V=isneg?-1:0; + else + V=(man>>sh_amt) | ((man & 1ULL<<(DOUBLE_MAN+1)) ? (DOUBLE_MAN_MASK>>(DOUBLE_MAN+2-sh_amt) <<(DOUBLE_MAN+2-sh_amt)):0); + + if (_AP_Q!=AP_TRN && !(_AP_Q==AP_TRN_ZERO && !_AP_S2)) { + const bool qb=((F2-_AP_F > DOUBLE_MAN+2) ? isneg : (man & (1ULL<<(F2-_AP_F-1))) != 0); + const int pos3=F2-_AP_F-2; + const bool r = (pos3>= 0) ? (man << AP_MAX(0, _AP_W2-pos3-1)& DOUBLE_MAN_MASK)!=0 : false; + carry = quantization_adjust(qb,r,isneg); + } + } + else { //no quantization + // V=man; + if (sh_amt < _AP_W) { + V = man; + V <<= sh_amt; + } + } + //handle overflow/underflow + if ((_AP_O != AP_WRAP || _AP_N != 0) && + ((!_AP_S && _AP_S2) || _AP_I-_AP_S < + _AP_I2-_AP_S2+(QUAN_INC|| (_AP_S2 && + _AP_O==AP_SAT_SYM)) )) {// saturation + bool deleted_zeros = _AP_S2?true:!carry, + deleted_ones = true; + bool neg_src; + const bool lD=(_AP_I2>_AP_I) && (_AP_W2-_AP_I2+_AP_I>=0) && (man & (1ULL <<(DOUBLE_MAN+2-_AP_I2+_AP_I))); + int pos1=F2+_AP_W-_AP_F; + if (pos1 < _AP_W2) { + int pos2=pos1+1; + bool Range1_all_ones=true; + bool Range1_all_zeros=true; + if (pos1>=0) { + ap_private<_AP_W,_AP_S> Range1= + ap_private<_AP_W,_AP_S>((man >> pos1) | ((1ULL<<(DOUBLE_MAN+1)&man) ? (DOUBLE_MAN_MASK >> (DOUBLE_MAN+2-pos1) <<(DOUBLE_MAN+2-pos1)):0)); + Range1_all_ones = Range1.isAllOnesValue(); // Range1.isAllOnesValue(); + Range1_all_zeros = Range1.isMinValue(); // Range1.isMinValue(); + } else { + Range1_all_ones=false; + Range1_all_zeros = man==0; // man.isMinValue(); + } + bool Range2_all_ones=true; + if (pos2<_AP_W2 && pos2>=0) { + ap_private<_AP_W, _AP_S> Range2= + ap_private<_AP_W, _AP_S>((man >> pos2) | ((1ULL<<(DOUBLE_MAN+1)&man) ? (DOUBLE_MAN_MASK >> (DOUBLE_MAN+2-pos2) <<(DOUBLE_MAN+2-pos2)):0)); + Range2_all_ones=Range2.isAllOnesValue(); // Range2.isAllOnesValue(); + } else if (pos2<0) + Range2_all_ones=false; + deleted_zeros=deleted_zeros && (carry?Range1_all_ones:Range1_all_zeros); + deleted_ones=carry?Range2_all_ones&&(F2-_AP_F+_AP_W<0||!lD) : Range1_all_ones; + neg_src=isneg&&!(carry&Range1_all_ones); + } else + neg_src = isneg && V[_AP_W -1]; + + const bool neg_trg=V.isNegative(); + const bool overflow=(neg_trg||!deleted_zeros) && !isneg; + bool underflow=(!neg_trg||!deleted_ones)&&neg_src; + //printf("neg_src = %d, neg_trg = %d, deleted_zeros = %d, + // deleted_ones = %d, overflow = %d, underflow = %d\n", + // neg_src, neg_trg, deleted_zeros, deleted_ones, + // overflow, underflow); + if (_AP_O==AP_SAT_SYM && _AP_S2 && _AP_S) + underflow |= neg_src && (_AP_W>1?V.isMinSignedValue():true); + overflow_adjust(underflow,overflow,lD, neg_src); + } + } + report(); + } + + + ///assign operators + //------------------------------------------------------------------------- + + INLINE volatile ap_fixed_base& operator=(const ap_fixed_base<_AP_W, _AP_I, _AP_S, + _AP_Q, _AP_O, _AP_N>& op) volatile { + V = op.V; + return *this; + } + + INLINE ap_fixed_base& operator=(const ap_fixed_base<_AP_W, _AP_I, _AP_S, + _AP_Q, _AP_O, _AP_N>& op) { + V = op.V; + return *this; + } + + INLINE volatile ap_fixed_base& operator=(const volatile ap_fixed_base<_AP_W, _AP_I, _AP_S, + _AP_Q, _AP_O, _AP_N>& op) volatile { + V = op.V; + return *this; + } + + INLINE ap_fixed_base& operator=(const volatile ap_fixed_base<_AP_W, _AP_I, _AP_S, + _AP_Q, _AP_O, _AP_N>& op) { + V = op.V; + return *this; + } + + // Set this ap_fixed_base with a bits string. That means the ssdm_int::V + // inside this ap_fixed_base is assigned by bv. + // Note the input parameter should be a fixed-point formatted bit string. + INLINE ap_fixed_base& setBits(unsigned long long bv) { + V=bv; + return *this; + } + + // Return a ap_fixed_base object whose ssdm_int::V is assigned by bv. + // Note the input parameter should be a fixed-point formatted bit string. + static INLINE ap_fixed_base bitsToFixed(unsigned long long bv) { + ap_fixed_base Tmp=bv; + return Tmp; + } + + // Explicit conversion functions to ap_private that captures + // all integer bits (bits are truncated) + INLINE ap_private + to_ap_private(bool Cnative = true) const { + ap_private ret = ap_private ((_AP_I >= 1) ? (_AP_S==true ? V.ashr(AP_MAX(0,_AP_W - _AP_I)) : V.lshr(AP_MAX(0,_AP_W - _AP_I))) : ap_private<_AP_W, _AP_S>(0)); + + if (Cnative) { + bool r = false; + if (_AP_I < _AP_W) { + if (_AP_I > 0) r = !(V.getLoBits(_AP_W - _AP_I).isMinValue()); + else r = !(V.isMinValue()); + } + if (r && V.isNegative()) { // if this is negative integer + ++ret;//ap_private(1,_AP_S); + } + } else { + //Follow OSCI library, conversion from sc_fixed to sc_int + } + return ret; + } + + template + INLINE operator ap_private<_AP_W2,_AP_S2> () const { + return (ap_private<_AP_W2,_AP_S2>)to_ap_private(); + } + + template + INLINE operator ap_private<_AP_W2,_AP_S2,_AP_N2> () const { + return (ap_private<_AP_W2,_AP_S2,_AP_N2>)to_ap_private(); + } + + //Explict conversion function to C built-in integral type + INLINE int to_int() const { + return to_ap_private().to_int(); + } + + INLINE int to_uint() const { + return to_ap_private().to_uint(); + } + + INLINE ap_slong to_int64() const { + return to_ap_private().to_int64(); + } + + INLINE ap_ulong to_uint64() const { + return to_ap_private().to_uint64(); + } + + INLINE double to_double() const { + if (!V) + return 0; + if (_AP_W>64 || (_AP_W - _AP_I) > 0) { + bool isneg = _AP_S && V[_AP_W-1]; + uint64_t res = isneg ? 0x8000000000000000ULL : 0; + ap_private<_AP_W, false> tmp = V; + if (isneg) tmp = -tmp; + int i = _AP_W -1 - tmp.countLeadingZeros(); + int exp = _AP_I-(_AP_W-i); + res|=((uint64_t)(exp+DOUBLE_BIAS))<DOUBLE_MAN)?tmp.lshr(i-DOUBLE_MAN):tmp).to_uint64() & DOUBLE_MAN_MASK; + res |= i 0) { + /* This specialization is disabled. It is giving wrong results in some cases. + bool isneg=V.isNegative(); + double dp = V.get(); + dp /= (1<< (_AP_W - _AP_I)); + return dp;*/ + } else + return double(to_int64()); + } + + INLINE float to_float() const { + uint32_t res=0; + if (V==0) + return 0; + bool isneg=V.isNegative(); + ap_private<_AP_W, _AP_S> tmp=V; + if (isneg) tmp = -tmp; + if (_AP_W-_AP_I>0||_AP_W>64) { + if (isneg) + res=0x80000000; + int i=_AP_W-1; + i-=tmp.countLeadingZeros(); + int exp=_AP_I-(_AP_W-i); + res|=(exp+FLOAT_BIAS)< man = 0; + if (i!=0) { + tmp.clear(i); + if (i>FLOAT_MAN) + man=tmp.lshr(i-FLOAT_MAN); + else + man=tmp; + res |= i < FLOAT_MAN?man.getZExtValue()<<(FLOAT_MAN-i):man.getZExtValue(); + } + } else { + return float(to_int64()); + } + float dp=rawBitsToFloat(res); + return dp; + } + + INLINE operator double () const { + return to_double(); + } +#ifndef __SC_COMPATIBLE__ + INLINE operator float () const { + return to_float(); + } + + INLINE operator char () const { + return (char) to_int(); + } + + INLINE operator unsigned char () const { + return (unsigned char) to_uint(); + } + + INLINE operator short () const { + return (short) to_int(); + } + + INLINE operator unsigned short () const { + return (unsigned short) to_uint(); + } + + INLINE operator int () const { + return to_int(); + } + + INLINE operator unsigned int () const { + return to_uint(); + } +#if 1 +#ifdef __x86_64__ + INLINE operator long () const { + return (long)to_int64(); + } + + INLINE operator unsigned long () const { + return (unsigned long) to_uint64(); + } +#else + INLINE operator long () const { + return to_int64(); + } + + INLINE operator unsigned long () const { + return to_uint64(); + } + +#endif +#endif + INLINE operator unsigned long long () const { + return to_uint64(); + } + + INLINE operator long long () const { + return to_int64(); + } +#endif + + INLINE std::string to_string(uint8_t radix=2, bool sign=false) const; + + INLINE ap_slong bits_to_int64() const { + ap_private res(V); + return (ap_slong) res; + } + + INLINE ap_ulong bits_to_uint64() const { + ap_private res(V); + return (ap_ulong) res; + } + + INLINE int length() const {return _AP_W;} + + // Count the number of zeros from the most significant bit + // to the first one bit. Note this is only for ap_fixed_base whose + // _AP_W <= 64, otherwise will incur assertion. + INLINE int countLeadingZeros() { + return V.countLeadingZeros(); + } + + ///Arithmetic:Binary + //------------------------------------------------------------------------- + template + INLINE typename RType<_AP_W2,_AP_I2,_AP_S2>::mult + operator * (const ap_fixed_base<_AP_W2,_AP_I2,_AP_S2,_AP_Q2,_AP_O2, _AP_N2>& op2) const { + typename RType<_AP_W2,_AP_I2,_AP_S2>::mult r; + r.V = V * op2.V; + return r; + } + + template + static INLINE ap_fixed_base multiply(const ap_fixed_base<_AP_W1,_AP_I1,_AP_S1>& op1, const + ap_fixed_base<_AP_W2,_AP_I2,_AP_S2>& op2) { + ap_private<_AP_W+_AP_W2, _AP_S> OP1=op1.V; + ap_private<_AP_W2,_AP_S2> OP2=op2.V; + return OP1*OP2; + } + + template + INLINE typename RType<_AP_W2,_AP_I2,_AP_S2>::div + operator / (const ap_fixed_base<_AP_W2,_AP_I2,_AP_S2,_AP_Q2,_AP_O2, _AP_N2>& op2) const { + enum {F2 = _AP_W2-_AP_I2, _W1=AP_MAX(_AP_W + AP_MAX(F2, 0), _AP_W2), + _W2=AP_MAX(_AP_W2,AP_MAX(_AP_W + AP_MAX(F2, 0), _AP_W2))}; + ap_private<_W1, _AP_S> dividend = (ap_private<_W1, _AP_S>(V)) << ((_W1>_AP_W)?F2:0); + ap_private<_W1, _AP_S2> divisior = ap_private<_W2, _AP_S2>(op2.V); + ap_private<_W1, _AP_S> ret = ap_private<_W1,_AP_S> ((_AP_S||_AP_S2) ? dividend.sdiv(divisior): dividend.udiv(divisior)); + typename RType<_AP_W2, _AP_I2, _AP_S2>::div r; + r.V = ret; + return r; + } +#define OP_BIN_AF(Sym, Rty, Width, Sign, Fun) \ + template \ + INLINE typename RType<_AP_W2,_AP_I2,_AP_S2>::Rty \ + operator Sym (const ap_fixed_base<_AP_W2,_AP_I2,_AP_S2,_AP_Q2,_AP_O2, _AP_N2>& op2) const \ + { \ + enum {_AP_F=_AP_W-_AP_I, F2=_AP_W2-_AP_I2}; \ + typename RType<_AP_W2,_AP_I2,_AP_S2>::Rty r, lhs(*this), rhs(op2); \ + r.V = lhs.V.Fun(rhs.V); \ + return r; \ + } \ + INLINE typename RType<_AP_W,_AP_I,_AP_S>::Rty \ + operator Sym (const ap_fixed_base& op2) const \ + { \ + typename RType<_AP_W,_AP_I,_AP_S>::Rty r; \ + r.V = V Sym op2.V; \ + return r; \ + } \ + + OP_BIN_AF(+, plus, plus_w, plus_s, Add) + OP_BIN_AF(-, minus, minus_w, minus_s, Sub) + +#define OP_LOGIC_BIN_AF(Sym, Rty, Width, Sign) \ + template \ + INLINE typename RType<_AP_W2,_AP_I2,_AP_S2>::Rty \ + operator Sym (const ap_fixed_base<_AP_W2,_AP_I2,_AP_S2,_AP_Q2,_AP_O2, _AP_N2>& op2) const \ + { \ + typename RType<_AP_W2,_AP_I2,_AP_S2>::Rty r, lhs(*this), rhs(op2); \ + r.V=lhs.V Sym rhs.V; \ + return r; \ + } \ + INLINE typename RType<_AP_W,_AP_I,_AP_S>::Rty \ + operator Sym (const ap_fixed_base& op2) const \ + { \ + typename RType<_AP_W,_AP_I,_AP_S>::Rty r; \ + r.V = V Sym op2.V; \ + return r; \ + } \ + INLINE typename RType<_AP_W,_AP_I,_AP_S>::Rty operator Sym(int op2) const \ + { \ + return V Sym (op2<<(_AP_W - _AP_I)); \ + } + OP_LOGIC_BIN_AF(&, logic, logic_w, logic_s) + OP_LOGIC_BIN_AF(|, logic, logic_w, logic_s) + OP_LOGIC_BIN_AF(^, logic, logic_w, logic_s) + + ///Arithmic : assign + //------------------------------------------------------------------------- +#define OP_ASSIGN_AF(Sym) \ + template \ + INLINE ap_fixed_base& operator Sym##= (const ap_fixed_base<_AP_W2,_AP_I2,_AP_S2,_AP_Q2,_AP_O2, _AP_N2>& op2) \ + { \ + *this=operator Sym (op2) ; \ + return *this; \ + } + + OP_ASSIGN_AF(+) + OP_ASSIGN_AF(-) + OP_ASSIGN_AF(&) + OP_ASSIGN_AF(|) + OP_ASSIGN_AF(^) + OP_ASSIGN_AF(*) + OP_ASSIGN_AF(/) + + ///Prefix increment, decrement + //------------------------------------------------------------------------- + INLINE ap_fixed_base& operator ++() { + operator+=(ap_fixed_base<1,1,false>(1)); //SystemC's semantics + return *this; + } + + INLINE ap_fixed_base& operator --() { + operator-=(ap_fixed_base<1,1,false>(1)); //SystemC's semantics + return *this; + } + + //Postfix increment, decrement + //------------------------------------------------------------------------- + INLINE const ap_fixed_base operator ++(int) { + ap_fixed_base t(*this); + operator++(); + return t; + } + + INLINE const ap_fixed_base operator --(int) { + ap_fixed_base t = *this; + operator--(); + return t; + } + + ///Unary arithmetic + //------------------------------------------------------------------------- + INLINE ap_fixed_base operator +() {return *this;} + + INLINE ap_fixed_base<_AP_W + 1, _AP_I + 1, true> operator -() const { + ap_fixed_base<_AP_W + 1, _AP_I + 1, true> Tmp(*this); + Tmp.V = - Tmp.V; + return Tmp; + } + + INLINE ap_fixed_base<_AP_W,_AP_I,true,_AP_Q,_AP_O, _AP_N> getNeg() { + ap_fixed_base<_AP_W,_AP_I,true,_AP_Q,_AP_O, _AP_N> Tmp(*this); + Tmp.V=-Tmp.V; + return Tmp; + } + + ///Not (!) + //------------------------------------------------------------------------- + INLINE bool operator !() const { + return !V; + } + + ///Bitwise complement + //------------------------------------------------------------------------- + INLINE ap_fixed_base<_AP_W, _AP_I, _AP_S> + operator ~() const { + ap_fixed_base<_AP_W, _AP_I, _AP_S> res(*this); + res.V.flip(); + return res; + } + + ///Shift + ///template argument as shift value + template + INLINE ap_fixed_base<_AP_W, _AP_I + _AP_SHIFT, _AP_S> lshift () const { + ap_fixed_base<_AP_W, _AP_I + _AP_SHIFT, _AP_S> r; + r.V = V; + return r; + } + + template + INLINE ap_fixed_base<_AP_W, _AP_I - _AP_SHIFT, _AP_S> rshift () const { + ap_fixed_base<_AP_W, _AP_I - _AP_SHIFT, _AP_S> r; + r.V = V; + return r; + } + + //Because the return type is the type of the the first operand, shift assign + //operators do not carry out any quantization or overflow + //While systemc, shift assigns for sc_fixed/sc_ufixed will result in + //quantization or overflow (depending on the mode of the first operand) + //------------------------------------------------------------------------- + INLINE ap_fixed_base operator << (int sh) const { + ap_fixed_base r; + bool isNeg=(sh&0x80000000) != 0; + sh=isNeg?-sh:sh; + bool shiftoverflow = sh >= _AP_W; + bool NegSrc = V.isNegative(); + if (isNeg) { + if (shiftoverflow) + NegSrc?r.V.set():r.V.clear(); + else + r.V=_AP_S?V.ashr(sh):V.lshr(sh); + } else { + if (shiftoverflow) + r.V.clear(); + else + r.V=V< 1 && sh <= _AP_W) + rb = (V << (_AP_W - sh + 1 )) != 0; + else if (sh > _AP_W) + rb = V != 0; + r.quantization_adjust(qb, rb, NegSrc); + } else if (isNeg == false && _AP_O != AP_WRAP) { + bool allones, allzeros; + if (sh < _AP_W ) { + ap_private<_AP_W, _AP_S > range1 = V.lshr(_AP_W - sh - 1); + allones = range1.isAllOnesValue(); + allzeros = range1.isMinValue(); + } else { + allones = false; + allzeros = V.isMinValue(); + } + bool overflow = !allzeros && !NegSrc; + bool underflow = !allones && NegSrc; + if (_AP_O == AP_SAT_SYM && _AP_S) + underflow |= NegSrc && (_AP_W > 1 ? r.V.isMinSignedValue():true); + bool lD = false; + if ( sh < _AP_W ) lD = V[_AP_W - sh - 1]; + r.overflow_adjust(underflow, overflow, lD, NegSrc); + } +#endif + return r; + } + + template + INLINE ap_fixed_base operator<<(const ap_private<_AP_W2,true>& op2) const { + int sh = op2.to_int(); + return operator << (sh); + } + + INLINE ap_fixed_base operator << (unsigned int sh ) const { + ap_fixed_base r; + bool shiftoverflow = sh >= _AP_W; + r.V = shiftoverflow ? ap_private<_AP_W, _AP_S >(0) : V << sh; + if (sh == 0) return r; +#ifdef __SC_COMPATIBLE__ + bool NegSrc = V.isNegative(); + if (_AP_O != AP_WRAP) { + bool allones, allzeros; + if (sh < _AP_W ) { + ap_private<_AP_W, _AP_S > range1 = V.lshr(_AP_W - sh -1); + allones = range1.isAllOnesValue(); + allzeros = range1.isMinValue(); + } else { + allones = false; + allzeros = V.isMinValue(); + } + bool overflow = !allzeros && !NegSrc; + bool underflow = !allones && NegSrc; + if (_AP_O == AP_SAT_SYM && _AP_S) + underflow |= NegSrc && (_AP_W > 1 ? r.V.isMinSignedValue():true); + bool lD = false; + if ( sh < _AP_W ) lD = V[_AP_W - sh - 1]; + r.overflow_adjust(underflow, overflow, lD, NegSrc); + } +#endif + return r; + } + + template + INLINE ap_fixed_base operator << (const ap_private<_AP_W2,false>& op2) const { + unsigned int sh = op2.to_uint(); + return operator << (sh); + } + + INLINE ap_fixed_base operator >> (int sh) const { + ap_fixed_base r; + bool isNeg=(sh&0x80000000) != 0; + bool NegSrc = V.isNegative(); + sh=isNeg?-sh:sh; + bool shiftoverflow = sh >= _AP_W; + if (isNeg && !shiftoverflow) r.V=V< 1 && sh <= _AP_W) + rb = (V << (_AP_W - sh + 1 )) != 0; + else if (sh > _AP_W) + rb = V != 0; + r.quantization_adjust(qb, rb, NegSrc); + } else if (isNeg == true && _AP_O != AP_WRAP) { + bool allones, allzeros; + if (sh < _AP_W ) { + ap_private<_AP_W, _AP_S > range1 = V.lshr(_AP_W - sh - 1); + allones = range1.isAllOnesValue(); + allzeros = range1.isMinValue(); + } else { + allones = false; + allzeros = V.isMinValue(); + } + bool overflow = !allzeros && !NegSrc; + bool underflow = !allones && NegSrc; + if (_AP_O == AP_SAT_SYM && _AP_S) + underflow |= NegSrc && (_AP_W > 1 ? r.V.isMinSignedValue():true); + bool lD = false; + if ( sh < _AP_W ) lD = V[_AP_W - sh - 1]; + r.overflow_adjust(underflow, overflow, lD, NegSrc); + } +#endif + return r; + } + + template + INLINE ap_fixed_base operator >> (const ap_private<_AP_W2,true>& op2) const { + int sh = op2.to_int(); + return operator >> (sh); + } + + INLINE ap_fixed_base operator >> (unsigned int sh) const { + ap_fixed_base r; + bool NegSrc = V.isNegative(); + bool shiftoverflow = sh >= _AP_W; + if (shiftoverflow) + NegSrc?r.V.set():r.V.clear(); + else + r.V=_AP_S?V.ashr(sh):V.lshr(sh); +#ifdef __SC_COMPATIBLE__ + if (sh == 0) return r; + if (_AP_Q != AP_TRN) { + bool qb = false; + if (sh <= _AP_W) qb = V[sh - 1]; + bool rb = false; + if (sh > 1 && sh <= _AP_W) + rb = (V << (_AP_W - sh + 1 )) != 0; + else if (sh > _AP_W) + rb = V != 0; + r.quantization_adjust(qb, rb, NegSrc); + } +#endif + return r; + } + + template + INLINE ap_fixed_base operator >> (const ap_private<_AP_W2,false>& op2) const { + unsigned int sh = op2.to_uint(); + return operator >> (sh); + } + + ///shift assign + //------------------------------------------------------------------------- +#define OP_AP_SHIFT_AP_ASSIGN_AF(Sym) \ + template \ + INLINE ap_fixed_base& operator Sym##=(const ap_private<_AP_W2,_AP_S2>& op2) \ + { \ + *this=operator Sym (op2); \ + return *this; \ + } + + OP_AP_SHIFT_AP_ASSIGN_AF(<<) + OP_AP_SHIFT_AP_ASSIGN_AF(>>) + + ///Support shift(ap_fixed_base) +#define OP_AP_SHIFT_AF(Sym) \ + template \ + INLINE ap_fixed_base operator Sym (const ap_fixed_base<_AP_W2,_AP_I2,_AP_S2,_AP_Q2,_AP_O2, _AP_N2>& op2) const \ + { \ + return operator Sym (op2.to_ap_private()); \ + } \ + template \ + INLINE ap_fixed_base& operator Sym##= (const ap_fixed_base<_AP_W2,_AP_I2,_AP_S2,_AP_Q2,_AP_O2, _AP_N2>& op2) \ + { \ + *this=operator Sym (op2); \ + return *this; \ + } + + OP_AP_SHIFT_AF(<<) + OP_AP_SHIFT_AF(>>) + + INLINE ap_fixed_base& operator >>= (unsigned int sh) { + *this = operator >> (sh); + return *this; + } + + INLINE ap_fixed_base& operator <<= (unsigned int sh) { + *this = operator << (sh); + return *this; + } + + INLINE ap_fixed_base& operator >>= (int sh) { + *this = operator >> (sh); + return *this; + } + + INLINE ap_fixed_base& operator <<= (int sh) { + *this = operator << (sh); + return *this; + } + + ///Comparisons + //------------------------------------------------------------------------- + template + INLINE bool operator == (const ap_fixed_base<_AP_W2,_AP_I2,_AP_S2,_AP_Q2,_AP_O2, _AP_N2>& op2) const { + enum {_AP_F=_AP_W-_AP_I,F2=_AP_W2-_AP_I2, shAmt1 = AP_MAX(F2-_AP_F, 0), shAmt2 = AP_MAX(_AP_F-F2,0), _AP_W3 = (_AP_F==F2) ? AP_MAX(_AP_W,_AP_W2) : AP_MAX(_AP_W+shAmt1, _AP_W2+shAmt2)}; + ap_private<_AP_W3, _AP_S > OP1= ap_private<_AP_W3, _AP_S >(V)< OP2=ap_private<_AP_W3,_AP_S2 >(op2.V)< + INLINE bool operator != (const ap_fixed_base<_AP_W2,_AP_I2,_AP_S2,_AP_Q2,_AP_O2, _AP_N2>& op2) const { + return !(*this==op2); + } + + template + INLINE bool operator > (const ap_fixed_base<_AP_W2,_AP_I2,_AP_S2,_AP_Q2,_AP_O2, _AP_N2>& op2) const { + enum {_AP_F=_AP_W-_AP_I,F2=_AP_W2-_AP_I2, shAmt1 = AP_MAX(F2-_AP_F, 0), shAmt2 = AP_MAX(_AP_F-F2,0), _AP_W3 = (_AP_F==F2) ? AP_MAX(_AP_W,_AP_W2) : AP_MAX(_AP_W+shAmt1, _AP_W2+shAmt2)}; + ap_private<_AP_W3, _AP_S > OP1= ap_private<_AP_W3, _AP_S >(V)< OP2=ap_private<_AP_W3,_AP_S2 >(op2.V)< + INLINE bool operator <= (const ap_fixed_base<_AP_W2,_AP_I2,_AP_S2,_AP_Q2,_AP_O2, _AP_N2>& op2) const { + return !(*this>op2); + } + + template + INLINE bool operator < (const ap_fixed_base<_AP_W2,_AP_I2,_AP_S2,_AP_Q2,_AP_O2, _AP_N2>& op2) const { + enum {_AP_F=_AP_W-_AP_I,F2=_AP_W2-_AP_I2, shAmt1 = AP_MAX(F2-_AP_F, 0), shAmt2 = AP_MAX(_AP_F-F2,0), _AP_W3 = (_AP_F==F2) ? AP_MAX(_AP_W,_AP_W2) : AP_MAX(_AP_W+shAmt1, _AP_W2+shAmt2)}; + ap_private<_AP_W3, _AP_S > OP1= ap_private<_AP_W3, _AP_S >(V)< OP2=ap_private<_AP_W3,_AP_S2 >(op2.V)< + INLINE bool operator >= (const ap_fixed_base<_AP_W2,_AP_I2,_AP_S2,_AP_Q2,_AP_O2, _AP_N2>& op2) const { + return !(*this) + DOUBLE_CMP_AF(>=) + DOUBLE_CMP_AF(<) + DOUBLE_CMP_AF(<=) + + // Bit and Slice Select + INLINE af_bit_ref<_AP_W,_AP_I,_AP_S,_AP_Q,_AP_O, _AP_N> operator [] (unsigned int index) { + assert(index<_AP_W&&"Attemping to read bit beyond MSB"); + return af_bit_ref<_AP_W,_AP_I,_AP_S,_AP_Q,_AP_O, _AP_N>(this, index); + } + + INLINE af_bit_ref<_AP_W, _AP_I,_AP_S,_AP_Q,_AP_O, _AP_N> bit(unsigned int index) { + assert(index < _AP_W && "Attempting to read bit beyond MSB"); + return af_bit_ref<_AP_W,_AP_I,_AP_S,_AP_Q,_AP_O, _AP_N>(this, index); + } + + template + INLINE af_bit_ref<_AP_W,_AP_I,_AP_S,_AP_Q,_AP_O, _AP_N> bit (const ap_private<_AP_W2,_AP_S2>& index) { + assert(index >= 0 && "Attempting to read bit with negative index"); + assert(index < _AP_W && "Attempting to read bit beyond MSB"); + return af_bit_ref<_AP_W,_AP_I,_AP_S,_AP_Q,_AP_O, _AP_N>(this, index.to_int()); + } + + INLINE bool bit (unsigned int index) const { + assert(index < _AP_W && "Attempting to read bit beyond MSB"); + return V[index]; + } + + INLINE bool operator [] (unsigned int index) const { + assert(index < _AP_W && "Attempting to read bit beyond MSB"); + return V[index]; + } + + template + INLINE bool bit (const ap_private<_AP_W2, _AP_S2>& index) const { + assert(index < _AP_W && "Attempting to read bit beyond MSB"); + return V[index.to_uint()]; + } + + template + INLINE bool operator [] (const ap_private<_AP_W2, _AP_S2>& index) const { + assert(index < _AP_W && "Attempting to read bit beyond MSB"); + return V[index.to_uint()]; + } + + INLINE af_bit_ref<_AP_W, _AP_I,_AP_S,_AP_Q,_AP_O, _AP_N> get_bit(int index) { + assert(index < _AP_I && "Attempting to read bit beyond MSB"); + assert(index >= _AP_I - _AP_W&& "Attempting to read bit beyond MSB"); + return af_bit_ref<_AP_W,_AP_I,_AP_S,_AP_Q,_AP_O, _AP_N>(this, index + _AP_W - _AP_I); + } + + template + INLINE af_bit_ref<_AP_W,_AP_I,_AP_S,_AP_Q,_AP_O, _AP_N> get_bit (const ap_private<_AP_W2, true>& index) { + assert(index >= _AP_I - _AP_W && "Attempting to read bit with negative index"); + assert(index < _AP_I && "Attempting to read bit beyond MSB"); + return af_bit_ref<_AP_W,_AP_I,_AP_S,_AP_Q,_AP_O, _AP_N>(this, index.to_int() + _AP_W - _AP_I); + } + + INLINE bool get_bit (int index) const { + assert(index >= _AP_I - _AP_W && "Attempting to read bit with negative index"); + assert(index < _AP_I && "Attempting to read bit beyond MSB"); + return V[index + _AP_W - _AP_I]; + } + + template + INLINE bool get_bit (const ap_private<_AP_W2, true>& index) const { + assert(index >= _AP_I - _AP_W && "Attempting to read bit with negative index"); + assert(index < _AP_I && "Attempting to read bit beyond MSB"); + return V[index.to_int() + _AP_W - _AP_I]; + } + + INLINE af_range_ref<_AP_W,_AP_I,_AP_S, _AP_Q, _AP_O, _AP_N> + range(int Hi, int Lo) { + assert((Hi < _AP_W) && (Lo < _AP_W) && "Out of bounds in range()"); + return af_range_ref<_AP_W, _AP_I, _AP_S, _AP_Q, _AP_O, _AP_N>(this, Hi, Lo); + } + + INLINE af_range_ref<_AP_W, _AP_I, _AP_S, _AP_Q, _AP_O, _AP_N> + operator () (int Hi, int Lo) { + assert((Hi < _AP_W) && (Lo < _AP_W) && "Out of bounds in range()"); + return af_range_ref<_AP_W, _AP_I, _AP_S, _AP_Q, _AP_O, _AP_N>(this, Hi, Lo); + } + + INLINE af_range_ref<_AP_W, _AP_I, _AP_S, _AP_Q, _AP_O, _AP_N> + range(int Hi, int Lo) const { + assert((Hi < _AP_W) && (Lo < _AP_W) &&"Out of bounds in range()"); + return af_range_ref<_AP_W, _AP_I, _AP_S, _AP_Q, _AP_O, _AP_N>(const_cast(this), Hi, Lo); + } + + INLINE af_range_ref<_AP_W, _AP_I, _AP_S, _AP_Q, _AP_O, _AP_N> + operator () (int Hi, int Lo) const { + return this->range(Hi, Lo); + } + + template + INLINE af_range_ref<_AP_W,_AP_I,_AP_S, _AP_Q, _AP_O, _AP_N> + range(const ap_private<_AP_W2, _AP_S2> &HiIdx, + const ap_private<_AP_W3, _AP_S3> &LoIdx) { + int Hi = HiIdx.to_int(); + int Lo = LoIdx.to_int(); + assert((Hi < _AP_W) && (Lo < _AP_W) && "Out of bounds in range()"); + return af_range_ref<_AP_W, _AP_I, _AP_S, _AP_Q, _AP_O, _AP_N>(this, Hi, Lo); + } + + template + INLINE af_range_ref<_AP_W,_AP_I,_AP_S, _AP_Q, _AP_O, _AP_N> + operator () (const ap_private<_AP_W2, _AP_S2> &HiIdx, + const ap_private<_AP_W3, _AP_S3> &LoIdx) { + int Hi = HiIdx.to_int(); + int Lo = LoIdx.to_int(); + assert((Hi < _AP_W) && (Lo < _AP_W) && "Out of bounds in range()"); + return af_range_ref<_AP_W, _AP_I, _AP_S, _AP_Q, _AP_O, _AP_N>(this, Hi, Lo); + } + + template + INLINE af_range_ref<_AP_W,_AP_I,_AP_S, _AP_Q, _AP_O, _AP_N> + range(const ap_private<_AP_W2, _AP_S2> &HiIdx, + const ap_private<_AP_W3, _AP_S3> &LoIdx) const { + int Hi = HiIdx.to_int(); + int Lo = LoIdx.to_int(); + assert((Hi < _AP_W) && (Lo < _AP_W) && "Out of bounds in range()"); + return af_range_ref<_AP_W, _AP_I, _AP_S, _AP_Q, _AP_O, _AP_N>(const_cast< + ap_fixed_base<_AP_W, _AP_I, _AP_S, _AP_Q, _AP_O, _AP_N>*>(this), + Hi, Lo); + } + + template + INLINE af_range_ref<_AP_W,_AP_I,_AP_S, _AP_Q, _AP_O, _AP_N> + operator () (const ap_private<_AP_W2, _AP_S2> &HiIdx, + const ap_private<_AP_W3, _AP_S3> &LoIdx) const { + int Hi = HiIdx.to_int(); + int Lo = LoIdx.to_int(); + return this->range(Hi, Lo); + } + + INLINE af_range_ref<_AP_W, _AP_I, _AP_S, _AP_Q, _AP_O, _AP_N> + range() { + return this->range(_AP_W - 1, 0); + } + + INLINE af_range_ref<_AP_W, _AP_I, _AP_S, _AP_Q, _AP_O, _AP_N> + range() const { + return this->range(_AP_W - 1, 0); + } + + INLINE bool is_zero () const { + return V.isMinValue(); + } + + INLINE bool is_neg () const { + if (V.isNegative()) + return true; + return false; + } + + INLINE int wl () const { + return _AP_W; + } + + INLINE int iwl () const { + return _AP_I; + } + + INLINE ap_q_mode q_mode () const { + return _AP_Q; + } + + INLINE ap_o_mode o_mode () const { + return _AP_O; + } + + INLINE int n_bits () const { + return 0; + } + + //private: +public: + ap_private<_AP_W, _AP_S> V; +}; + +template +std::string ap_fixed_base<_AP_W, _AP_I, _AP_S, _AP_Q, _AP_O, _AP_N>::to_string( + uint8_t radix, bool sign) const { + std::string str; + str.clear(); + char step; + std::string prefix; + switch (radix) { + case 2 : prefix = "0b"; step = 1; break; + case 8 : prefix = "0o"; step = 3; break; + case 16 : prefix = "0x"; step = 4; break; + default : break; + } + if (_AP_W <= _AP_I) + str = this->to_ap_private().to_string(radix, + radix == 10 ? _AP_S : sign); + else { + if (radix == 10) { + bool isNeg = _AP_S && V.isNegative(); + if (_AP_I > 0) { + ap_private int_part(0); + int_part = this->to_ap_private(); + str += int_part.to_string(radix, false); + } else { + if (isNeg) str += '-'; + } + ap_fixed_base<_AP_W, _AP_I, _AP_S> tmp(*this); + if (isNeg && _AP_I <= 0) tmp = -tmp; + ap_fixed_base<_AP_W - AP_MIN(_AP_I, 0), 0, false> frac_part = tmp; + if (frac_part == 0) return str; + str += "."; + while (frac_part != 0) { + char digit = (frac_part * radix).to_ap_private(); + str += static_cast(digit + '0'); + frac_part *= radix; + } + } else { + if (_AP_I > 0) { + for (signed i = _AP_W - _AP_I; i < _AP_W; i += step) { + + char digit = (char)(this->range(AP_MIN(i + step - 1, _AP_W - 1), i)); + str = (digit < 10 ? static_cast(digit + '0') : + static_cast(digit - 10 + 'a')) + str; + } + } + str += '.'; + ap_fixed_base tmp(*this); + for (signed i = _AP_W - _AP_I - 1; i >= 0; i -= step) { + char digit = (char)(tmp.range(i, AP_MAX(0, i - step + 1))); + str += digit < 10 ? static_cast(digit + '0') : + static_cast(digit - 10 + 'a'); + } + } + } + str = prefix + str; + return str; +} + +template +INLINE void b_not(ap_fixed_base<_AP_W, _AP_I, _AP_S, _AP_Q, _AP_O, _AP_N>& ret, + const ap_fixed_base<_AP_W, _AP_I, _AP_S, _AP_Q, _AP_O, _AP_N>& op) { + ret.V = op.V; + ret.V.flip(); +} + +template +INLINE void b_and(ap_fixed_base<_AP_W, _AP_I, _AP_S, _AP_Q, _AP_O, _AP_N>& ret, + const ap_fixed_base<_AP_W, _AP_I, _AP_S, _AP_Q, _AP_O, _AP_N>& op1, + const ap_fixed_base<_AP_W, _AP_I, _AP_S, _AP_Q, _AP_O, _AP_N>& op2) { + ret.V = op1.V & op2.V; +} + +template +INLINE void b_or(ap_fixed_base<_AP_W, _AP_I, _AP_S, _AP_Q, _AP_O, _AP_N>& ret, + const ap_fixed_base<_AP_W, _AP_I, _AP_S, _AP_Q, _AP_O, _AP_N>& op1, + const ap_fixed_base<_AP_W, _AP_I, _AP_S, _AP_Q, _AP_O, _AP_N>& op2) { + ret.V = op1.V | op2.V; +} + +template +INLINE void b_xor(ap_fixed_base<_AP_W, _AP_I, _AP_S, _AP_Q, _AP_O, _AP_N>& ret, + const ap_fixed_base<_AP_W, _AP_I, _AP_S, _AP_Q, _AP_O, _AP_N>& op1, + const ap_fixed_base<_AP_W, _AP_I, _AP_S, _AP_Q, _AP_O, _AP_N>& op2) { + ret.V = op1.V ^ op2.V; +} + +template +INLINE void neg(ap_fixed_base<_AP_W, _AP_I, _AP_S, _AP_Q, _AP_O, _AP_N>& ret, + const ap_fixed_base<_AP_W2, _AP_I2, _AP_S2, _AP_Q2, _AP_O2, _AP_N2>& op) { + ap_fixed_base<_AP_W2+!_AP_S2, _AP_I2+!_AP_S2, true, _AP_Q2, _AP_O2, _AP_N2> Tmp; + Tmp.V = - op.V; + ret = Tmp; +} + +template +INLINE void neg(ap_fixed_base<_AP_W, _AP_I, _AP_S, _AP_Q, _AP_O, _AP_N>& ret, + const ap_fixed_base<_AP_W, _AP_I, _AP_S, _AP_Q, _AP_O, _AP_N>& op) { + ret.V = -op.V; +} + +template +INLINE void lshift(ap_fixed_base<_AP_W, _AP_I, _AP_S, _AP_Q, _AP_O, _AP_N>& ret, + const ap_fixed_base<_AP_W2, _AP_I2, _AP_S2, _AP_Q2, _AP_O2, _AP_N2>& op, + int i) { + ap_fixed_base<_AP_W2 - _AP_I2 + AP_MAX(_AP_I, _AP_I2), AP_MAX(_AP_I, _AP_I2), _AP_S2, _AP_Q2, _AP_O2, _AP_N2> Tmp; + Tmp = op; + Tmp.V <<= i; + ret = Tmp; +} + +template +INLINE void lshift(ap_fixed_base<_AP_W, _AP_I, _AP_S, _AP_Q, _AP_O, _AP_N>& ret, + const ap_fixed_base<_AP_W, _AP_I, _AP_S, _AP_Q, _AP_O, _AP_N>& op, + int i) { + ret.V = op.V << i; +} + +template +INLINE void rshift(ap_fixed_base<_AP_W, _AP_I, _AP_S, _AP_Q, _AP_O, _AP_N>& ret, + const ap_fixed_base<_AP_W2, _AP_I2, _AP_S2, _AP_Q2, _AP_O2, _AP_N2>& op, + int i) { + ap_fixed_base<_AP_I2 + AP_MAX(_AP_W - _AP_I, _AP_W2 - _AP_I2), _AP_I2, _AP_S2, _AP_Q2, _AP_O2, _AP_N2> Tmp; + Tmp = op; + Tmp.V = _AP_S2 ? Tmp.V.ashr(i): Tmp.V.lshr(i); + ret = Tmp; +} + +template +INLINE void rshift(ap_fixed_base<_AP_W, _AP_I, _AP_S, _AP_Q, _AP_O, _AP_N>& ret, + const ap_fixed_base<_AP_W, _AP_I, _AP_S, _AP_Q, _AP_O, _AP_N>& op, + int i) { + ret.V = _AP_S ? op.V.ashr(i): op.V.lshr(i); +} + +#define AF_CTOR_SPEC_BASE(_AP_W,_AP_S,C_TYPE) \ + template<> INLINE ap_fixed_base<_AP_W,_AP_W,_AP_S,AP_TRN,AP_WRAP>::ap_fixed_base(C_TYPE i_op):V(i_op) \ + { \ + } + +#define AF_CTOR_SPEC(__W,C_TYPE) \ + AF_CTOR_SPEC_BASE(__W,true,C_TYPE) \ + AF_CTOR_SPEC_BASE(__W,false,C_TYPE) + +AF_CTOR_SPEC(1,bool) +AF_CTOR_SPEC(8, signed char) +AF_CTOR_SPEC(8, unsigned char) +AF_CTOR_SPEC(16, signed short) +AF_CTOR_SPEC(16, unsigned short) +AF_CTOR_SPEC(32, signed int) +AF_CTOR_SPEC(32, unsigned int) +AF_CTOR_SPEC(64, ap_slong) +AF_CTOR_SPEC(64, ap_ulong) + +///Output streaming +//----------------------------------------------------------------------------- +template +INLINE std::ostream& +operator <<(std::ostream& os, const ap_fixed_base<_AP_W,_AP_I,_AP_S,_AP_Q,_AP_O, _AP_N>& x) { + os << x.to_double(); + return os; +} + +///Input streaming +//----------------------------------------------------------------------------- +template +INLINE std::istream& +operator >> (std::istream& os, ap_fixed_base<_AP_W,_AP_I,_AP_S,_AP_Q,_AP_O, _AP_N>& x) { + double d; + os >> d; + x = ap_fixed_base<_AP_W,_AP_I,_AP_S,_AP_Q,_AP_O, _AP_N>(x); + return os; +} + +template +INLINE void print(const ap_fixed_base<_AP_W,_AP_I,_AP_S,_AP_Q,_AP_O, _AP_N>& x) { + ap_private<_AP_W,_AP_S> data=x.V; + if (_AP_I>0) { + const ap_private<_AP_I,_AP_S> p1=data>>(_AP_W-_AP_I); + print(p1); + + } else + printf("0"); + printf("."); + if (_AP_I<_AP_W) { + const ap_private<_AP_W-_AP_I,false> p2=data; + print(p2,false); + } +} + +///Operators mixing Integers with ap_fixed_base +//----------------------------------------------------------------------------- +#if 1 +#define AF_BIN_OP_WITH_INT_SF(BIN_OP,C_TYPE,_AP_W2,_AP_S2,RTYPE) \ + template \ + INLINE typename ap_fixed_base<_AP_W,_AP_I,_AP_S>::template RType<_AP_W2,_AP_W2,_AP_S2>::RTYPE \ + operator BIN_OP (const ap_fixed_base<_AP_W,_AP_I,_AP_S,_AP_Q,_AP_O, _AP_N>& op, C_TYPE i_op) \ + { \ + return op.operator BIN_OP(ap_private<_AP_W2,_AP_S2>(i_op)); \ + } +#define AF_BIN_OP_WITH_INT(BIN_OP, C_TYPE, _AP_W2,_AP_S2,RTYPE) \ + template \ + INLINE typename ap_fixed_base<_AP_W,_AP_I,_AP_S>::template RType<_AP_W2,_AP_W2,_AP_S2>::RTYPE \ + operator BIN_OP (const ap_fixed_base<_AP_W,_AP_I,_AP_S,_AP_Q,_AP_O, _AP_N>& op, C_TYPE i_op) \ + { \ + return op.operator BIN_OP (ap_fixed_base<_AP_W2,_AP_W2,_AP_S2>(i_op)); \ + } \ + \ + template \ + INLINE typename ap_fixed_base<_AP_W,_AP_I,_AP_S>::template RType<_AP_W2,_AP_W2,_AP_S2>::RTYPE \ + operator BIN_OP (C_TYPE i_op, const ap_fixed_base<_AP_W,_AP_I,_AP_S,_AP_Q,_AP_O, _AP_N>& op) \ + { \ + return ap_fixed_base<_AP_W2,_AP_W2,_AP_S2>(i_op).operator BIN_OP (op); \ + } + +#else +#define AF_BIN_OP_WITH_INT_SF(BIN_OP,C_TYPE,_AP_W2,_AP_S2,RTYPE) \ + template \ + INLINE typename ap_fixed_base<_AP_W,_AP_I,_AP_S>::template RType<_AP_W2,_AP_W2,_AP_S2>::RTYPE \ + operator BIN_OP (const ap_fixed_base<_AP_W,_AP_I,_AP_S,_AP_Q,_AP_O, _AP_N>& op, C_TYPE i_op) \ + { \ + return op BIN_OP (i_op); \ + } +#define AF_BIN_OP_WITH_INT(BIN_OP, C_TYPE, _AP_W2,_AP_S2,RTYPE) \ + template \ + INLINE typename ap_fixed_base<_AP_W,_AP_I,_AP_S>::template RType<_AP_W2,_AP_W2,_AP_S2>::RTYPE \ + operator BIN_OP (const ap_fixed_base<_AP_W,_AP_I,_AP_S,_AP_Q,_AP_O, _AP_N>& op, C_TYPE i_op) \ + { \ + return op.V BIN_OP (i_op<<(_AP_W-_AP_I)); \ + } \ + \ + \ + template \ + INLINE typename ap_fixed_base<_AP_W,_AP_I,_AP_S>::template RType<_AP_W2,_AP_W2,_AP_S2>::RTYPE \ + operator BIN_OP (C_TYPE i_op, const ap_fixed_base<_AP_W,_AP_I,_AP_S,_AP_Q,_AP_O, _AP_N>& op) \ + { \ + return ap_fixed_base<_AP_W2,_AP_W2,_AP_S2>(i_op).operator BIN_OP (op); \ + } + +#endif +#if 1 +#define AF_REL_OP_WITH_INT(REL_OP, C_TYPE, _AP_W2,_AP_S2) \ + template \ + INLINE bool operator REL_OP (const ap_fixed_base<_AP_W,_AP_I,_AP_S,_AP_Q,_AP_O, _AP_N>& op, C_TYPE i_op) \ + { \ + return op.operator REL_OP (ap_fixed_base<_AP_W2,_AP_W2,_AP_S2>(i_op)); \ + } \ + \ + \ + template \ + INLINE bool operator REL_OP (C_TYPE i_op, const ap_fixed_base<_AP_W,_AP_I,_AP_S,_AP_Q,_AP_O, _AP_N>& op) \ + { \ + return ap_fixed_base<_AP_W2,_AP_W2,_AP_S2>(i_op).operator REL_OP (op); \ + } +#else +#define AF_REL_OP_WITH_INT(REL_OP, C_TYPE, _AP_W2,_AP_S2) \ + template \ + INLINE bool operator REL_OP (const ap_fixed_base<_AP_W,_AP_I,_AP_S,_AP_Q,_AP_O, _AP_N>& op, C_TYPE i_op) \ + { \ + return op.V.operator REL_OP (i_op<<(_AP_W-_AP_I)); \ + } \ + \ + \ + template \ + INLINE bool operator REL_OP (C_TYPE i_op, const ap_fixed_base<_AP_W,_AP_I,_AP_S,_AP_Q,_AP_O, _AP_N>& op) \ + { \ + return (i_op<<(_AP_W-_AP_I)) REL_OP (op.V.VAL); \ + } +#endif +#if 1 +#define AF_ASSIGN_OP_WITH_INT(ASSIGN_OP, C_TYPE, _AP_W2, _AP_S2) \ + template \ + INLINE ap_fixed_base<_AP_W,_AP_I,_AP_S,_AP_Q,_AP_O, _AP_N>& operator ASSIGN_OP ( ap_fixed_base<_AP_W,_AP_I,_AP_S,_AP_Q,_AP_O, _AP_N>& op, C_TYPE i_op) { \ + return op.operator ASSIGN_OP (ap_fixed_base<_AP_W2,_AP_W2,_AP_S2>(i_op)); \ + } +#define AF_ASSIGN_OP_WITH_INT_SF(ASSIGN_OP, C_TYPE, _AP_W2, _AP_S2) \ + template \ + INLINE ap_fixed_base<_AP_W,_AP_I,_AP_S,_AP_Q,_AP_O, _AP_N>& operator ASSIGN_OP ( ap_fixed_base<_AP_W,_AP_I,_AP_S,_AP_Q,_AP_O, _AP_N>& op, C_TYPE i_op) { \ + return op.operator ASSIGN_OP (ap_private<_AP_W2,_AP_S2>(i_op)); \ + } +#else +#define AF_ASSIGN_OP_WITH_INT(ASSIGN_OP, C_TYPE, _AP_W2, _AP_S2) \ + template \ + INLINE ap_fixed_base<_AP_W,_AP_I,_AP_S,_AP_Q,_AP_O, _AP_N>& operator ASSIGN_OP ( ap_fixed_base<_AP_W,_AP_I,_AP_S,_AP_Q,_AP_O, _AP_N>& op, C_TYPE i_op) { \ + return op.V.operator ASSIGN_OP (i_op); \ + } +#define AF_ASSIGN_OP_WITH_INT_SF(ASSIGN_OP, C_TYPE, _AP_W2, _AP_S2) \ + template \ + INLINE ap_fixed_base<_AP_W,_AP_I,_AP_S,_AP_Q,_AP_O, _AP_N>& operator ASSIGN_OP ( ap_fixed_base<_AP_W,_AP_I,_AP_S,_AP_Q,_AP_O, _AP_N>& op, C_TYPE i_op) { \ + return op.V.operator ASSIGN_OP (i_op); \ + } +#endif + +#define AF_OPS_WITH_INT(C_TYPE, WI, SI) \ + AF_BIN_OP_WITH_INT(+, C_TYPE, WI, SI, plus) \ + AF_BIN_OP_WITH_INT(-, C_TYPE, WI, SI, minus) \ + AF_BIN_OP_WITH_INT(*, C_TYPE, WI, SI, mult) \ + AF_BIN_OP_WITH_INT(/, C_TYPE, WI, SI, div) \ + AF_BIN_OP_WITH_INT_SF(>>, C_TYPE, WI, SI, arg1) \ + AF_BIN_OP_WITH_INT_SF(<<, C_TYPE, WI, SI, arg1) \ + AF_BIN_OP_WITH_INT(&, C_TYPE, WI, SI, logic) \ + AF_BIN_OP_WITH_INT(|, C_TYPE, WI, SI, logic) \ + AF_BIN_OP_WITH_INT(^, C_TYPE, WI, SI, logic) \ + \ + AF_REL_OP_WITH_INT(==, C_TYPE, WI, SI) \ + AF_REL_OP_WITH_INT(!=, C_TYPE, WI, SI) \ + AF_REL_OP_WITH_INT(>, C_TYPE, WI, SI) \ + AF_REL_OP_WITH_INT(>=, C_TYPE, WI, SI) \ + AF_REL_OP_WITH_INT(<, C_TYPE, WI, SI) \ + AF_REL_OP_WITH_INT(<=, C_TYPE, WI, SI) \ + \ + AF_ASSIGN_OP_WITH_INT(+=, C_TYPE, WI, SI) \ + AF_ASSIGN_OP_WITH_INT(-=, C_TYPE, WI, SI) \ + AF_ASSIGN_OP_WITH_INT(*=, C_TYPE, WI, SI) \ + AF_ASSIGN_OP_WITH_INT(/=, C_TYPE, WI, SI) \ + AF_ASSIGN_OP_WITH_INT_SF(>>=, C_TYPE, WI, SI) \ + AF_ASSIGN_OP_WITH_INT_SF(<<=, C_TYPE, WI, SI) \ + AF_ASSIGN_OP_WITH_INT(&=, C_TYPE, WI, SI) \ + AF_ASSIGN_OP_WITH_INT(|=, C_TYPE, WI, SI) \ + AF_ASSIGN_OP_WITH_INT(^=, C_TYPE, WI, SI) + +AF_OPS_WITH_INT(bool, 1, false) +AF_OPS_WITH_INT(char, 8, true) +AF_OPS_WITH_INT(signed char, 8, true) +AF_OPS_WITH_INT(unsigned char, 8, false) +AF_OPS_WITH_INT(short, 16, true) +AF_OPS_WITH_INT(unsigned short, 16, false) +AF_OPS_WITH_INT(int, 32, true) +AF_OPS_WITH_INT(unsigned int, 32, false) +# if defined __x86_64__ +AF_OPS_WITH_INT(long, 64, true) +AF_OPS_WITH_INT(unsigned long, 64, false) +# else +AF_OPS_WITH_INT(long, 32, true) +AF_OPS_WITH_INT(unsigned long, 32, false) +# endif +AF_OPS_WITH_INT(ap_slong, 64, true) +AF_OPS_WITH_INT(ap_ulong, 64, false) + +#define AF_BIN_OP_WITH_AP_INT(BIN_OP, RTYPE) \ + template \ + INLINE typename ap_fixed_base<_AP_W2,_AP_W2,_AP_S2>::template RType<_AP_W,_AP_I,_AP_S>::RTYPE \ + operator BIN_OP ( const ap_private<_AP_W2,_AP_S2>& i_op, const ap_fixed_base<_AP_W,_AP_I,_AP_S,_AP_Q,_AP_O, _AP_N>& op) { \ + return ap_fixed_base<_AP_W2,_AP_W2,_AP_S2>(i_op).operator BIN_OP (op); \ + } \ + template \ + INLINE typename ap_fixed_base<_AP_W,_AP_I,_AP_S>::template RType<_AP_W2,_AP_W2,_AP_S2>::RTYPE \ + operator BIN_OP ( const ap_fixed_base<_AP_W,_AP_I,_AP_S,_AP_Q,_AP_O, _AP_N>& op, const ap_private<_AP_W2,_AP_S2>& i_op) { \ + return op.operator BIN_OP (ap_fixed_base<_AP_W2,_AP_W2,_AP_S2>(i_op)); \ + } + +#define AF_REL_OP_WITH_AP_INT(REL_OP) \ + template \ + INLINE bool operator REL_OP ( const ap_fixed_base<_AP_W,_AP_I,_AP_S,_AP_Q,_AP_O, _AP_N>& op, const ap_private<_AP_W2,_AP_S2>& i_op) { \ + return op.operator REL_OP ( ap_fixed_base<_AP_W2,_AP_W2,_AP_S2>(i_op)); \ + } \ + template \ + INLINE bool operator REL_OP ( const ap_private<_AP_W2,_AP_S2>& i_op, const ap_fixed_base<_AP_W,_AP_I,_AP_S,_AP_Q,_AP_O, _AP_N>& op) { \ + return ap_fixed_base<_AP_W2,_AP_W2,_AP_S2>(i_op).operator REL_OP (op); \ + } + +#define AF_ASSIGN_OP_WITH_AP_INT(ASSIGN_OP) \ + template \ + INLINE ap_fixed_base<_AP_W,_AP_I,_AP_S,_AP_Q,_AP_O, _AP_N>& operator ASSIGN_OP ( ap_fixed_base<_AP_W,_AP_I,_AP_S,_AP_Q,_AP_O, _AP_N>& op, const ap_private<_AP_W2,_AP_S2>& i_op) { \ + return op.operator ASSIGN_OP (ap_fixed_base<_AP_W2,_AP_W2,_AP_S2>(i_op)); \ + } \ + template \ + INLINE ap_private<_AP_W2,_AP_S2>& operator ASSIGN_OP ( ap_private<_AP_W2,_AP_S2>& i_op, const ap_fixed_base<_AP_W,_AP_I,_AP_S,_AP_Q,_AP_O, _AP_N>& op) { \ + return i_op.operator ASSIGN_OP (op.to_ap_private()); \ + } + +AF_BIN_OP_WITH_AP_INT(+, plus) +AF_BIN_OP_WITH_AP_INT(-, minus) +AF_BIN_OP_WITH_AP_INT(*, mult) +AF_BIN_OP_WITH_AP_INT(/, div) +AF_BIN_OP_WITH_AP_INT(&, logic) +AF_BIN_OP_WITH_AP_INT(|, logic) +AF_BIN_OP_WITH_AP_INT(^, logic) + +AF_REL_OP_WITH_AP_INT(==) +AF_REL_OP_WITH_AP_INT(!=) +AF_REL_OP_WITH_AP_INT(>) +AF_REL_OP_WITH_AP_INT(>=) +AF_REL_OP_WITH_AP_INT(<) +AF_REL_OP_WITH_AP_INT(<=) + +AF_ASSIGN_OP_WITH_AP_INT(+=) +AF_ASSIGN_OP_WITH_AP_INT(-=) +AF_ASSIGN_OP_WITH_AP_INT(*=) +AF_ASSIGN_OP_WITH_AP_INT(/=) +AF_ASSIGN_OP_WITH_AP_INT(&=) +AF_ASSIGN_OP_WITH_AP_INT(|=) +AF_ASSIGN_OP_WITH_AP_INT(^=) + +#define AF_REF_REL_OP_MIX_INT(REL_OP, C_TYPE, _AP_W2, _AP_S2) \ +template \ + INLINE bool operator REL_OP ( const af_range_ref<_AP_W,_AP_I, _AP_S, _AP_Q, _AP_O, _AP_N> &op, C_TYPE op2) { \ + return (ap_private<_AP_W, false>(op)).operator REL_OP (ap_private<_AP_W2,_AP_S2>(op2)); \ + } \ +template \ + INLINE bool operator REL_OP ( C_TYPE op2, const af_range_ref<_AP_W, _AP_I, _AP_S, _AP_Q, _AP_O, _AP_N> &op) { \ + return ap_private<_AP_W2,_AP_S2>(op2).operator REL_OP (ap_private<_AP_W, false>(op)); \ + } \ +template \ + INLINE bool operator REL_OP ( const af_bit_ref<_AP_W, _AP_I, _AP_S, _AP_Q, _AP_O, _AP_N> &op, C_TYPE op2) { \ + return (bool(op)) REL_OP op2; \ + } \ +template \ + INLINE bool operator REL_OP ( C_TYPE op2, const af_bit_ref<_AP_W, _AP_I, _AP_S, _AP_Q, _AP_O, _AP_N> &op) { \ + return op2 REL_OP (bool(op)); \ + } + +#define AF_REF_REL_MIX_INT(C_TYPE, _AP_WI, _AP_SI) \ +AF_REF_REL_OP_MIX_INT(>, C_TYPE, _AP_WI, _AP_SI) \ +AF_REF_REL_OP_MIX_INT(<, C_TYPE, _AP_WI, _AP_SI) \ +AF_REF_REL_OP_MIX_INT(>=, C_TYPE, _AP_WI, _AP_SI) \ +AF_REF_REL_OP_MIX_INT(<=, C_TYPE, _AP_WI, _AP_SI) \ +AF_REF_REL_OP_MIX_INT(==, C_TYPE, _AP_WI, _AP_SI) \ +AF_REF_REL_OP_MIX_INT(!=, C_TYPE, _AP_WI, _AP_SI) + +AF_REF_REL_MIX_INT(bool, 1, false) +AF_REF_REL_MIX_INT(char, 8, true) +AF_REF_REL_MIX_INT(signed char, 8, true) +AF_REF_REL_MIX_INT(unsigned char, 8, false) +AF_REF_REL_MIX_INT(short, 16, true) +AF_REF_REL_MIX_INT(unsigned short, 16, false) +AF_REF_REL_MIX_INT(int, 32, true) +AF_REF_REL_MIX_INT(unsigned int, 32, false) +# if defined __x86_64__ +AF_REF_REL_MIX_INT(long, 64, true) +AF_REF_REL_MIX_INT(unsigned long, 64, false) +# else +AF_REF_REL_MIX_INT(long, 32, true) +AF_REF_REL_MIX_INT(unsigned long, 32, false) +# endif +AF_REF_REL_MIX_INT(ap_slong, 64, true) +AF_REF_REL_MIX_INT(ap_ulong, 64, false) + +#define AF_REF_REL_OP_AP_INT(REL_OP) \ +template \ + INLINE bool operator REL_OP ( const af_range_ref<_AP_W,_AP_I, _AP_S, _AP_Q, _AP_O, _AP_N> &op, const ap_private<_AP_W2, _AP_S> &op2) { \ + return (ap_private<_AP_W, false>(op)).operator REL_OP (op2); \ + } \ +template \ + INLINE bool operator REL_OP (const ap_private<_AP_W2, _AP_S2> &op2, const af_range_ref<_AP_W, _AP_I, _AP_S, _AP_Q, _AP_O, _AP_N> &op) { \ + return op2.operator REL_OP (ap_private<_AP_W, false>(op)); \ + } \ +template \ + INLINE bool operator REL_OP ( const af_bit_ref<_AP_W, _AP_I, _AP_S, _AP_Q, _AP_O, _AP_N> &op, const ap_private<_AP_W2, _AP_S2> &op2) { \ + return (ap_private<1, false>(op)).operator REL_OP (op2); \ + } \ +template \ + INLINE bool operator REL_OP ( const ap_private<_AP_W2, _AP_S2> &op2, const af_bit_ref<_AP_W, _AP_I, _AP_S, _AP_Q, _AP_O, _AP_N> &op) { \ + return op2.operator REL_OP (ap_private<1,false>(op)); \ + } + +AF_REF_REL_OP_AP_INT(>) +AF_REF_REL_OP_AP_INT(<) +AF_REF_REL_OP_AP_INT(>=) +AF_REF_REL_OP_AP_INT(<=) +AF_REF_REL_OP_AP_INT(==) +AF_REF_REL_OP_AP_INT(!=) + +// Relational Operators with double +template +INLINE bool operator == ( double op1, const ap_fixed_base<_AP_W,_AP_I,_AP_S,_AP_Q,_AP_O, _AP_N>& op2) { + return op2.operator == (op1); +} + +template +INLINE bool operator != ( double op1, const ap_fixed_base<_AP_W,_AP_I,_AP_S,_AP_Q,_AP_O, _AP_N>& op2) { + return op2.operator != (op1); +} + +template +INLINE bool operator > ( double op1, const ap_fixed_base<_AP_W,_AP_I,_AP_S,_AP_Q,_AP_O, _AP_N>& op2) { + return op2.operator < (op1); +} + +template +INLINE bool operator >= ( double op1, const ap_fixed_base<_AP_W,_AP_I,_AP_S,_AP_Q,_AP_O, _AP_N>& op2) { + return op2.operator <= (op1); +} + +template +INLINE bool operator < ( double op1, const ap_fixed_base<_AP_W,_AP_I,_AP_S,_AP_Q,_AP_O, _AP_N>& op2) { + return op2.operator > (op1); +} + +template +INLINE bool operator <= ( double op1, const ap_fixed_base<_AP_W,_AP_I,_AP_S,_AP_Q,_AP_O, _AP_N>& op2) { + return op2.operator >= (op1); +} + +#endif /* #ifndef __AESL_GCC_AP_FIXED_H__ */ \ No newline at end of file diff --git a/router/etc/ap_int_sim.h b/router/etc/ap_int_sim.h new file mode 100644 index 0000000..887ccd8 --- /dev/null +++ b/router/etc/ap_int_sim.h @@ -0,0 +1,1629 @@ +/* + * Copyright 2012 Xilinx, Inc. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef __AESL_GCC_AP_INT_H__ +#define __AESL_GCC_AP_INT_H__ + +#ifndef __cplusplus +#error C++ is required to include this header file +#endif /* #ifndef __cplusplus */ + +#undef _AP_DEBUG_ +#include +#include + +// for safety +#if (defined(_AP_N)|| defined(_AP_C)) +#error One or more of the following is defined: _AP_N, _AP_C. Definition conflicts with their usage as template parameters. +#endif /* #if (defined(_AP_N)|| defined(_AP_C)) */ + +// for safety +#if (defined(_AP_W) || defined(_AP_I) || defined(_AP_S) || defined(_AP_Q) || defined(_AP_O) || defined(_AP_W2) || defined(_AP_I2) || defined(_AP_S2) || defined(_AP_Q2) || defined(_AP_O2)) +#error One or more of the following is defined: _AP_W, _AP_I, _AP_S, _AP_Q, _AP_O, _AP_W2, _AP_I2, _AP_S2, _AP_Q2, _AP_O2. Definition conflicts with their usage as template parameters. +#endif /* #if (defined(_AP_W) || defined(_AP_I) || defined(_AP_S) || defined(_AP_Q) || defined(_AP_O) || defined(_AP_W2) || defined(_AP_I2) || defined(_AP_S2) || defined(_AP_Q2) || defined(_AP_O2)) */ + +//for safety +#if (defined(_AP_W3) || defined(_AP_S3) || defined(_AP_W4) || defined(_AP_S4)) +#error One or more of the following is defined: _AP_W3, _AP_S3, _AP_W4,_AP_S4. Definition conflicts with their usage as template parameters. +#endif /* #if (defined(_AP_W3) || defined(_AP_S3) || defined(_AP_W4) || defined(_AP_S4)) */ + +//for safety +#if (defined(_AP_W1) || defined(_AP_S1) || defined(_AP_I1) || defined(_AP_T) || defined(_AP_T1) || defined(_AP_T2) || defined(_AP_T3) || defined(_AP_T4)) +#error One or more of the following is defined: _AP_W1, _AP_S1, _AP_I1, _AP_T, _AP_T1, _AP_T2, _AP_T3, _AP_T4. Definition conflicts with their usage as template parameters. +#endif /* #if (defined(_AP_W1) || defined(_AP_S1) || defined(_AP_I1) || defined(_AP_T) || defined(_AP_T1) || defined(_AP_T2) || defined(_AP_T3) || defined(_AP_T4)) */ + +#define __AESL_APDT_IN_SCFLOW__ +#ifndef __AESL_APDT_IN_SCFLOW__ + #include "etc/ap_private.h" +#else + #include "../etc/ap_private.h" +#endif /* #ifndef __AESL_APDT_IN_SCFLOW__ */ + +#ifdef _AP_DEBUG_ + #define AP_DEBUG(s) s +#else + #define AP_DEBUG(s) +#endif /* #ifdef _AP_DEBUG_ */ + +#ifndef __SIMULATION__ + #define __SIMULATION__ +#endif /* #ifndef __SIMULATION__ */ + +#if !(defined SYSTEMC_H) && !(defined SYSTEMC_INCLUDED) + #ifndef SC_TRN + #define SC_TRN AP_TRN + #endif /* #ifndef SC_TRN */ + #ifndef SC_RND + #define SC_RND AP_RND + #endif /* #ifndef SC_RND */ + #ifndef SC_TRN_ZERO + #define SC_TRN_ZERO AP_TRN_ZERO + #endif /* #ifndef SC_TRN_ZERO */ + #ifndef SC_RND_ZERO + #define SC_RND_ZERO AP_RND_ZERO + #endif /* #ifndef SC_RND_ZERO */ + #ifndef SC_RND_INF + #define SC_RND_INF AP_RND_INF + #endif /* #ifndef SC_RND_INF */ + #ifndef SC_RND_MIN_INF + #define SC_RND_MIN_INF AP_RND_MIN_INF + #endif /* #ifndef SC_RND_MIN_INF */ + #ifndef SC_RND_CONV + #define SC_RND_CONV AP_RND_CONV + #endif /* #ifndef SC_RND_CONV */ + #ifndef SC_WRAP + #define SC_WRAP AP_WRAP + #endif /* #ifndef SC_WRAP */ + #ifndef SC_SAT + #define SC_SAT AP_SAT + #endif /* #ifndef SC_SAT */ + #ifndef SC_SAT_ZERO + #define SC_SAT_ZERO AP_SAT_ZERO + #endif /* #ifndef SC_SAT_ZERO */ + #ifndef SC_SAT_SYM + #define SC_SAT_SYM AP_SAT_SYM + #endif /* #ifndef SC_SAT_SYM */ + #ifndef SC_WRAP_SM + #define SC_WRAP_SM AP_WRAP_SM + #endif /* #ifndef SC_WRAP_SM */ + #ifndef SC_BIN + #define SC_BIN AP_BIN + #endif /* #ifndef SC_BIN */ + #ifndef SC_OCT + #define SC_OCT AP_OCT + #endif /* #ifndef SC_OCT */ + #ifndef SC_DEC + #define SC_DEC AP_DEC + #endif /* #ifndef SC_DEC */ + #ifndef SC_HEX + #define SC_HEX AP_HEX + #endif /* #ifndef SC_HEX */ +#endif /* #if !(defined SYSTEMC_H) && !(defined SYSTEMC_INCLUDED) */ +#ifndef AP_INT_MAX_W +#define AP_INT_MAX_W 1024 +#endif +#define BIT_WIDTH_UPPER_LIMIT (1 << 15) +#if AP_INT_MAX_W > BIT_WIDTH_UPPER_LIMIT +#error "Bitwidth exceeds 32768 (1 << 15), the maximum allowed value" +#endif +#define MAX_MODE(BITS) ((BITS + 1023) / 1024) + +///Forward declaration +template struct ap_range_ref; +template struct ap_bit_ref; + +template struct ap_fixed_base; +template struct af_range_ref; +template struct af_bit_ref; +template class ap_uint; + +enum { + AP_BIN = 2, + AP_OCT = 8, + AP_DEC = 10, + AP_HEX = 16 +}; + +///Why to use reference? +///Because we will operate the original object indirectly by operating the +///result object directly after concating or part selecting + +///Proxy class which allows concatination to be used as rvalue(for reading) and +//lvalue(for writing) + +/// Concatination reference. +// ---------------------------------------------------------------- +template +struct ap_concat_ref { +#ifdef _MSC_VER + #pragma warning(disable: 4521 4522) +#endif /* #ifdef _MSC_VER */ + enum {_AP_WR=_AP_W1+_AP_W2,}; + _AP_T1& mbv1; + _AP_T2& mbv2; + + INLINE ap_concat_ref(const ap_concat_ref<_AP_W1, _AP_T1, + _AP_W2, _AP_T2>& ref): + mbv1(ref.mbv1), mbv2(ref.mbv2) {} + + INLINE ap_concat_ref(_AP_T1& bv1, _AP_T2& bv2):mbv1(bv1),mbv2(bv2) {} + + template + INLINE ap_concat_ref& operator = (const ap_private<_AP_W3,_AP_S3>& val) { + ap_private<_AP_W1+_AP_W2, false> vval(val); + int W_ref1=mbv1.length(); + int W_ref2=mbv2.length(); + ap_private<_AP_W1,false> mask1(-1); + mask1>>=_AP_W1-W_ref1; + ap_private<_AP_W2,false> mask2(-1); + mask2>>=_AP_W2-W_ref2; + mbv1.set(ap_private<_AP_W1,false>((vval>>W_ref2)&mask1)); + mbv2.set(ap_private<_AP_W2,false>(vval&mask2)); + return *this; + } + + INLINE ap_concat_ref& operator = (unsigned long long val) { + ap_private<_AP_W1+_AP_W2, false> tmpVal(val); + return operator = (tmpVal); + } + + template + INLINE ap_concat_ref& operator = + (const ap_concat_ref <_AP_W3, _AP_T3, _AP_W4, _AP_T4>& val) { + ap_private<_AP_W1+_AP_W2, false> tmpVal(val); + return operator = (tmpVal); + } + + INLINE ap_concat_ref& operator = + (const ap_concat_ref <_AP_W1, _AP_T1, _AP_W2, _AP_T2>& val) { + ap_private<_AP_W1+_AP_W2, false> tmpVal(val); + return operator = (tmpVal); + } + + template + INLINE ap_concat_ref& operator =(const ap_bit_ref<_AP_W3, _AP_S3>& val) { + ap_private<_AP_W1+_AP_W2, false> tmpVal(val); + return operator = (tmpVal); + } + + template + INLINE ap_concat_ref& operator =(const ap_range_ref<_AP_W3,_AP_S3>& val) { + ap_private<_AP_W1+_AP_W2, false> tmpVal(val); + return operator =(tmpVal); + } + + template + INLINE ap_concat_ref& operator= (const af_range_ref<_AP_W3, _AP_I3, _AP_S3, + _AP_Q3, _AP_O3, _AP_N3>& val) { + return operator = ((const ap_private<_AP_W3, false>)(val)); + } + + template + INLINE ap_concat_ref& operator= (const ap_fixed_base<_AP_W3, _AP_I3, _AP_S3, + _AP_Q3, _AP_O3, _AP_N3>& val) { + return operator = (val.to_ap_private()); + } + + template + INLINE ap_concat_ref& operator= (const af_bit_ref<_AP_W3, _AP_I3, _AP_S3, + _AP_Q3, _AP_O3, _AP_N3>& val) { + return operator=((unsigned long long)(bool)(val)); + } + + + INLINE operator ap_private<_AP_WR, false> () const { + return get(); + } + + INLINE operator unsigned long long () const { + return get().to_uint64(); + } + + template + INLINE ap_concat_ref<_AP_WR, ap_concat_ref, _AP_W3, ap_range_ref<_AP_W3, _AP_S3> > + operator, (const ap_range_ref<_AP_W3, _AP_S3> &a2) { + return ap_concat_ref<_AP_WR, ap_concat_ref, + _AP_W3, ap_range_ref<_AP_W3, _AP_S3> >(*this, + const_cast &>(a2)); + } + + template + INLINE ap_concat_ref<_AP_WR, ap_concat_ref, _AP_W3, ap_private<_AP_W3, _AP_S3> > + operator, (ap_private<_AP_W3, _AP_S3> &a2) { + return ap_concat_ref<_AP_WR, ap_concat_ref, + _AP_W3, ap_private<_AP_W3, _AP_S3> >(*this, a2); + } + + template + INLINE ap_concat_ref<_AP_WR, ap_concat_ref, _AP_W3, ap_private<_AP_W3, _AP_S3> > + operator, (const ap_private<_AP_W3, _AP_S3> &a2) { + return ap_concat_ref<_AP_WR, ap_concat_ref, + _AP_W3, ap_private<_AP_W3, _AP_S3> >(*this, + const_cast&>(a2)); + } + + template + INLINE ap_concat_ref<_AP_WR, ap_concat_ref, 1, ap_bit_ref<_AP_W3, _AP_S3> > + operator, (const ap_bit_ref<_AP_W3, _AP_S3> &a2) { + return ap_concat_ref<_AP_WR, ap_concat_ref, + 1, ap_bit_ref<_AP_W3, _AP_S3> >(*this, + const_cast &>(a2)); + } + + template + INLINE ap_concat_ref<_AP_WR, ap_concat_ref, _AP_W3+_AP_W4, ap_concat_ref<_AP_W3,_AP_T3,_AP_W4,_AP_T4> > + operator, (const ap_concat_ref<_AP_W3,_AP_T3,_AP_W4,_AP_T4> &a2) + { + return ap_concat_ref<_AP_WR, ap_concat_ref, + _AP_W3+_AP_W4, ap_concat_ref<_AP_W3,_AP_T3,_AP_W4, + _AP_T4> >(*this, const_cast& >(a2)); + } + + template + INLINE + ap_concat_ref<_AP_WR, ap_concat_ref, _AP_W3, af_range_ref<_AP_W3, _AP_I3, _AP_S3, _AP_Q3, _AP_O3, _AP_N3> > + operator, (const af_range_ref<_AP_W3, _AP_I3, _AP_S3, _AP_Q3, + _AP_O3, _AP_N3> &a2) { + return ap_concat_ref<_AP_WR, ap_concat_ref, _AP_W3, af_range_ref<_AP_W3, + _AP_I3, _AP_S3, _AP_Q3, _AP_O3, _AP_N3> >(*this, + const_cast& >(a2)); + } + + template + INLINE + ap_concat_ref<_AP_WR, ap_concat_ref, 1, af_bit_ref<_AP_W3, _AP_I3, _AP_S3, _AP_Q3, _AP_O3, _AP_N3> > + operator, (const af_bit_ref<_AP_W3, _AP_I3, _AP_S3, _AP_Q3, + _AP_O3, _AP_N3> &a2) { + return ap_concat_ref<_AP_WR, ap_concat_ref, 1, af_bit_ref<_AP_W3, + _AP_I3, _AP_S3, _AP_Q3, _AP_O3, _AP_N3> >(*this, + const_cast& >(a2)); + } + + template + INLINE ap_private + operator & (const ap_private<_AP_W3,_AP_S3>& a2) { + return get() & a2; + } + + + template + INLINE ap_private + operator | (const ap_private<_AP_W3,_AP_S3>& a2) { + return get() | a2; + } + + + template + INLINE ap_private + operator ^ (const ap_private<_AP_W3,_AP_S3>& a2) { + return ap_private(get() ^ a2); + } + + INLINE const ap_private<_AP_WR, false> get() const + { + ap_private<_AP_W1+_AP_W2, false> tmpVal = ap_private<_AP_W1+_AP_W2, false> (mbv1.get()); + ap_private<_AP_W1+_AP_W2, false> tmpVal2 = ap_private<_AP_W1+_AP_W2, false> (mbv2.get()); + int W_ref2 = mbv2.length(); + tmpVal <<= W_ref2; + tmpVal |= tmpVal2; + return tmpVal; + } + + INLINE const ap_private<_AP_WR, false> get() { + ap_private<_AP_W1+_AP_W2, false> tmpVal = ap_private<_AP_W1+_AP_W2, false> ( mbv1.get()); + ap_private<_AP_W1+_AP_W2, false> tmpVal2 = ap_private<_AP_W1+_AP_W2, false> (mbv2.get()); + int W_ref2 = mbv2.length(); + tmpVal <<= W_ref2; + tmpVal |= tmpVal2; + return tmpVal; + } + + template + INLINE void set(const ap_private<_AP_W3,false> & val) { + ap_private<_AP_W1+_AP_W2, false> vval(val); + int W_ref1=mbv1.length(); + int W_ref2=mbv2.length(); + ap_private<_AP_W1,false> mask1(-1); + mask1>>=_AP_W1-W_ref1; + ap_private<_AP_W2,false> mask2(-1); + mask2>>=_AP_W2-W_ref2; + mbv1.set(ap_private<_AP_W1,false>((vval>>W_ref2)&mask1)); + mbv2.set(ap_private<_AP_W2,false>(vval&mask2)); + } + + INLINE int length() const { + return mbv1.length()+mbv2.length(); + } + + INLINE std::string to_string(uint8_t radix=2) const { + return get().to_string(radix); + } +}; + +///Proxy class, which allows part selection to be used as rvalue(for reading) and +//lvalue(for writing) + +///Range(slice) reference +//------------------------------------------------------------ +template +struct ap_range_ref { +#ifdef _MSC_VER + #pragma warning( disable : 4521 4522 ) +#endif /* #ifdef _MSC_VER */ + ap_private<_AP_W,_AP_S> &d_bv; + int l_index; + int h_index; + +public: + INLINE ap_range_ref(const ap_range_ref<_AP_W, _AP_S>& ref): + d_bv(ref.d_bv), l_index(ref.l_index), h_index(ref.h_index) {} + + INLINE ap_range_ref(ap_private<_AP_W,_AP_S>* bv, int h, int l): + d_bv(*bv),l_index(l),h_index(h) { + //if (h < l) + //fprintf(stderr, "Warning! The bits selected will be returned in reverse order\n"); + } + + INLINE operator ap_private<_AP_W, false> () const { + ap_private<_AP_W, false> val(0); + if(h_index>=l_index) { + if (_AP_W > 64) { + val=d_bv; + ap_private<_AP_W,false> mask(-1); + mask>>=_AP_W-(h_index-l_index+1); + val>>=l_index; + val&=mask; + } else { + const static uint64_t mask = (~0ULL>> (64>_AP_W ? (64-_AP_W):0)); + val = (d_bv >> l_index) & (mask >>(_AP_W-(h_index-l_index+1))); + } + } else { + for(int i=0, j=l_index;j>=0&&j>=h_index;j--,i++) + if((d_bv)[j]) val.set(i); + } + return val; + } + + INLINE operator unsigned long long () const { + return to_uint64(); + } + + template + INLINE ap_range_ref& operator =(const ap_private<_AP_W2,_AP_S2>& val) { + ap_private<_AP_W,false> vval=ap_private<_AP_W,false>(val); + if (l_index>h_index) { + for (int i=0, j=l_index;j>=0&&j>=h_index;j--,i++) + (vval)[i]? d_bv.set(j):d_bv.clear(j); + } else { + if (_AP_W > 64) { + ap_private<_AP_W,false> mask(-1); + if (l_index>0) { + mask<<=l_index; + vval<<=l_index; + } + if(h_index<_AP_W-1) + { + ap_private<_AP_W,false> mask2(-1); + mask2>>=_AP_W-h_index-1; + mask&=mask2; + vval&=mask2; + } + mask.flip(); + d_bv&=mask; + d_bv|=vval; + } else { + unsigned shift = 64-_AP_W; + uint64_t mask = ~0ULL>>(shift); + if(l_index>0) + { + vval = mask & vval << l_index; + mask = mask & mask << l_index; + } + if(h_index<_AP_W-1) + { + uint64_t mask2 = mask; + mask2 >>= (_AP_W-h_index-1); + mask&=mask2; + vval&=mask2; + } + mask = ~mask; + d_bv&=mask; + d_bv|=vval; + } + } + return *this; + } + + INLINE ap_range_ref& operator = (unsigned long long val) + { + const ap_private<_AP_W,_AP_S> vval=val; + return operator = (vval); + } + + + INLINE ap_range_ref& operator =(const ap_range_ref<_AP_W, _AP_S>& val) + { + const ap_private<_AP_W, false> tmpVal(val); + return operator =(tmpVal); + } + + + + template + INLINE ap_range_ref& operator = + (const ap_concat_ref <_AP_W3, _AP_T3, _AP_W4, _AP_T4>& val) + { + const ap_private<_AP_W, false> tmpVal(val); + return operator = (tmpVal); + } + + template + INLINE ap_range_ref& operator =(const ap_range_ref<_AP_W3,_AP_S3>& val) + { + const ap_private<_AP_W, false> tmpVal(val); + return operator =(tmpVal); + } + + template + INLINE ap_range_ref& operator= (const af_range_ref<_AP_W2, _AP_I2, _AP_S2, + _AP_Q2, _AP_O2, _AP_N2>& val) { + return operator=((const ap_private<_AP_W2, _AP_S2>)(val)); + } + + template + INLINE ap_range_ref& operator= (const ap_fixed_base<_AP_W2, _AP_I2, _AP_S2, + _AP_Q2, _AP_O2, _AP_N2>& val) { + return operator=(val.to_ap_private()); + } + + template + INLINE ap_range_ref& operator= (const af_bit_ref<_AP_W2, _AP_I2, _AP_S2, + _AP_Q2, _AP_O2, _AP_N2>& val) { + return operator=((unsigned long long)(bool)(val)); + } + + template + INLINE ap_range_ref& operator= (const ap_bit_ref<_AP_W2, _AP_S2>& val) { + return operator=((unsigned long long)(bool)(val)); + } + + template + INLINE + ap_concat_ref<_AP_W,ap_range_ref,_AP_W2,ap_range_ref<_AP_W2,_AP_S2> > + operator, (const ap_range_ref<_AP_W2,_AP_S2> &a2) + { + return + ap_concat_ref<_AP_W, ap_range_ref, _AP_W2, + ap_range_ref<_AP_W2,_AP_S2> >(*this, + const_cast& >(a2)); + } + + + template + INLINE ap_concat_ref<_AP_W,ap_range_ref,_AP_W2,ap_private<_AP_W2,_AP_S2> > + operator , (ap_private<_AP_W2,_AP_S2>& a2) + { + return + ap_concat_ref<_AP_W, ap_range_ref, _AP_W2, ap_private<_AP_W2,_AP_S2> >(*this, a2); + } + + INLINE ap_concat_ref<_AP_W,ap_range_ref,_AP_W,ap_private<_AP_W,_AP_S> > + operator , (ap_private<_AP_W, _AP_S>& a2) + { + return + ap_concat_ref<_AP_W, ap_range_ref, _AP_W, + ap_private<_AP_W,_AP_S> >(*this, a2); + } + + + + template + INLINE + ap_concat_ref<_AP_W,ap_range_ref,1,ap_bit_ref<_AP_W2,_AP_S2> > + operator, (const ap_bit_ref<_AP_W2,_AP_S2> &a2) + { + return + ap_concat_ref<_AP_W, ap_range_ref, 1, + ap_bit_ref<_AP_W2,_AP_S2> >(*this, const_cast& >(a2)); + } + + + template + INLINE + ap_concat_ref<_AP_W, ap_range_ref, _AP_W2+_AP_W3, ap_concat_ref<_AP_W2, _AP_T2, _AP_W3, _AP_T3> > + operator, (const ap_concat_ref<_AP_W2, _AP_T2, _AP_W3, _AP_T3> &a2) + { + return ap_concat_ref<_AP_W, ap_range_ref, _AP_W2+_AP_W3, + ap_concat_ref<_AP_W2, _AP_T2, _AP_W3, _AP_T3> >(*this, + const_cast& >(a2)); + } + + template + INLINE + ap_concat_ref<_AP_W, ap_range_ref, _AP_W2, af_range_ref<_AP_W2, _AP_I2, _AP_S2, _AP_Q2, _AP_O2, _AP_N2> > + operator, (const af_range_ref<_AP_W2, _AP_I2, _AP_S2, _AP_Q2, + _AP_O2, _AP_N2> &a2) { + return ap_concat_ref<_AP_W, ap_range_ref, _AP_W2, af_range_ref<_AP_W2, + _AP_I2, _AP_S2, _AP_Q2, _AP_O2, _AP_N2> >(*this, + const_cast& >(a2)); + } + + template + INLINE + ap_concat_ref<_AP_W, ap_range_ref, 1, af_bit_ref<_AP_W2, _AP_I2, _AP_S2, _AP_Q2, _AP_O2, _AP_N2> > + operator, (const af_bit_ref<_AP_W2, _AP_I2, _AP_S2, _AP_Q2, + _AP_O2, _AP_N2> &a2) { + return ap_concat_ref<_AP_W, ap_range_ref, 1, af_bit_ref<_AP_W2, + _AP_I2, _AP_S2, _AP_Q2, _AP_O2, _AP_N2> >(*this, + const_cast& >(a2)); + } + + template + INLINE bool operator == (const ap_range_ref<_AP_W2, _AP_S2>& op2) + { + ap_private<_AP_W,false> lhs=get(); + ap_private<_AP_W2,false> rhs=op2.get(); + return lhs==rhs; + } + + + template + INLINE bool operator != (const ap_range_ref<_AP_W2, _AP_S2>& op2) + { + ap_private<_AP_W,false> lhs=get(); + ap_private<_AP_W2,false> rhs=op2.get(); + return lhs!=rhs; + } + + + template + INLINE bool operator > (const ap_range_ref<_AP_W2, _AP_S2>& op2) + { + ap_private<_AP_W,false> lhs=get(); + ap_private<_AP_W2,false> rhs=op2.get(); + return lhs>rhs; + } + + + template + INLINE bool operator >= (const ap_range_ref<_AP_W2, _AP_S2>& op2) + { + ap_private<_AP_W,false> lhs=get(); + ap_private<_AP_W2,false> rhs=op2.get(); + return lhs>=rhs; + } + + + template + INLINE bool operator < (const ap_range_ref<_AP_W2, _AP_S2>& op2) + { + ap_private<_AP_W,false> lhs=get(); + ap_private<_AP_W2,false> rhs=op2.get(); + return lhs + INLINE bool operator <= (const ap_range_ref<_AP_W2, _AP_S2>& op2) + { + ap_private<_AP_W,false> lhs=get(); + ap_private<_AP_W2,false> rhs=op2.get(); + return lhs<=rhs; + } + + + template + INLINE void set(const ap_private<_AP_W2,false>& val) + { + ap_private<_AP_W,_AP_S> vval=val; + if(l_index>h_index) + { + for(int i=0, j=l_index;j>=0&&j>=h_index;j--,i++) + (vval)[i]? d_bv.set(j):d_bv.clear(j); + } else { + if (_AP_W>64 ) { + ap_private<_AP_W,_AP_S> mask(-1); + if(l_index>0) + { + ap_private<_AP_W,false> mask1(-1); + mask1>>=_AP_W-l_index; + mask1.flip(); + mask=mask1; + //vval&=mask1; + vval<<=l_index; + } + if(h_index<_AP_W-1) + { + ap_private<_AP_W,false> mask2(-1); + mask2<<=h_index+1; + mask2.flip(); + mask&=mask2; + vval&=mask2; + } + mask.flip(); + d_bv&=mask; + d_bv|=vval; + } else { + uint64_t mask = ~0ULL >> (64-_AP_W); + if(l_index>0) + { + uint64_t mask1 = mask; + mask1=mask & (mask1>>(_AP_W-l_index)); + vval =mask&( vval <> (64-_AP_W); + mask2 = mask &(mask2<<(h_index+1)); + mask&=~mask2; + vval&=~mask2; + } + d_bv&=(~mask&(~0ULL >> (64-_AP_W))); + d_bv|=vval; + } + } + } + + + INLINE ap_private<_AP_W,false> get() const + { + ap_private<_AP_W,false> val(0); + if(h_index=0&&j>=h_index;j--,i++) + if((d_bv)[j]) val.set(i); + } else { + val=d_bv; + val>>=l_index; + if(h_index<_AP_W-1) + { + if (_AP_W <= 64) { + const static uint64_t mask = (~0ULL>> (64>_AP_W ? (64-_AP_W):0)); + val &= (mask>> (_AP_W-(h_index-l_index+1))); + } else { + ap_private<_AP_W,false> mask(-1); + mask>>=_AP_W-(h_index-l_index+1); + val&=mask; + } + } + } + return val; + } + + + INLINE ap_private<_AP_W,false> get() + { + ap_private<_AP_W,false> val(0); + if(h_index=0&&j>=h_index;j--,i++) + if((d_bv)[j]) val.set(i); + } else { + val=d_bv; + val>>=l_index; + if(h_index<_AP_W-1) + { + if (_AP_W <= 64 ) { + static const uint64_t mask = ~0ULL>> (64>_AP_W ? (64-_AP_W):0); + return val &= ( (mask) >> (_AP_W - (h_index-l_index+1))); + } else { + ap_private<_AP_W,false> mask(-1); + mask>>=_AP_W-(h_index-l_index+1); + val&=mask; + } + } + } + return val; + } + + + INLINE int length() const + { + return h_index>=l_index?h_index-l_index+1:l_index-h_index+1; + } + + + INLINE int to_int() const + { + ap_private<_AP_W,false> val=get(); + return val.to_int(); + } + + + INLINE unsigned int to_uint() const + { + ap_private<_AP_W,false> val=get(); + return val.to_uint(); + } + + + INLINE long to_long() const + { + ap_private<_AP_W,false> val=get(); + return val.to_long(); + } + + + INLINE unsigned long to_ulong() const + { + ap_private<_AP_W,false> val=get(); + return val.to_ulong(); + } + + + INLINE ap_slong to_int64() const + { + ap_private<_AP_W,false> val=get(); + return val.to_int64(); + } + + + INLINE ap_ulong to_uint64() const + { + ap_private<_AP_W,false> val=get(); + return val.to_uint64(); + } + + INLINE std::string to_string(uint8_t radix=2) const { + return get().to_string(radix); + } + +}; + +///Proxy class, which allows bit selection to be used as rvalue(for reading) and +//lvalue(for writing) + +///Bit reference +//-------------------------------------------------------------- +template +struct ap_bit_ref { +#ifdef _MSC_VER +#pragma warning( disable : 4521 4522 ) +#endif + ap_private<_AP_W,_AP_S>& d_bv; + int d_index; + +public: + INLINE ap_bit_ref(const ap_bit_ref<_AP_W, _AP_S>& ref): + d_bv(ref.d_bv), d_index(ref.d_index) {} + + INLINE ap_bit_ref(ap_private<_AP_W,_AP_S>& bv, int index=0): + d_bv(bv),d_index(index) + { +#ifdef _AP_DEBUG_ + assert(d_index<_AP_W&&"index out of bound"); +#endif + } + + + INLINE operator bool () const + { + return d_bv.get_bit(d_index); + } + + + INLINE bool to_bool() const + { + return operator bool (); + } + + + INLINE ap_bit_ref& operator = (unsigned long long val) + { + if(val) + d_bv.set(d_index); + else + d_bv.clear(d_index); + return *this; + } + + +#if 0 + INLINE ap_bit_ref& operator = (bool val) + { + if(val) + d_bv.set(d_index); + else + d_bv.clear(d_index); + return *this; + } +#endif + template + INLINE ap_bit_ref& operator =(const ap_private<_AP_W2,_AP_S2>& val) + { + return operator =((unsigned long long)(val != 0)); + } + + + template + INLINE ap_bit_ref& operator =(const ap_bit_ref<_AP_W2,_AP_S2>& val) + { + return operator =((unsigned long long)(bool)val); + } + + INLINE ap_bit_ref& operator =(const ap_bit_ref<_AP_W,_AP_S>& val) + { + return operator =((unsigned long long)(bool)val); + } + + template + INLINE ap_bit_ref& operator =(const ap_range_ref<_AP_W2,_AP_S2>& val) + { + return operator =((unsigned long long)(bool) val); + } + + + template + INLINE ap_bit_ref& operator= (const af_range_ref<_AP_W2, _AP_I2, _AP_S2, + _AP_Q2, _AP_O2, _AP_N2>& val) { + return operator=((const ap_private<_AP_W2, false>)(val)); + } + + template + INLINE ap_bit_ref& operator= (const af_bit_ref<_AP_W2, _AP_I2, _AP_S2, + _AP_Q2, _AP_O2, _AP_N2>& val) { + return operator=((unsigned long long)(bool)(val)); + } + + template + INLINE ap_bit_ref& operator= (const ap_concat_ref<_AP_W2, _AP_T3, _AP_W3, _AP_T3>& val) { + return operator=((const ap_private<_AP_W2 + _AP_W3, false>)(val)); + } + + + + template + INLINE ap_concat_ref<1, ap_bit_ref, _AP_W2, ap_private<_AP_W2,_AP_S2> > + operator , (ap_private<_AP_W2, _AP_S2>& a2) + { + return ap_concat_ref<1, ap_bit_ref, _AP_W2, ap_private<_AP_W2,_AP_S2> >(*this, a2); + } + + template + INLINE ap_concat_ref<1, ap_bit_ref, _AP_W2, ap_range_ref<_AP_W2,_AP_S2> > + operator, (const ap_range_ref<_AP_W2, _AP_S2> &a2) + { + return + ap_concat_ref<1, ap_bit_ref, _AP_W2, ap_range_ref<_AP_W2,_AP_S2> >(*this, + const_cast &>(a2)); + } + + + template + INLINE ap_concat_ref<1, ap_bit_ref, 1, ap_bit_ref<_AP_W2,_AP_S2> > + operator, (const ap_bit_ref<_AP_W2, _AP_S2> &a2) + { + return + ap_concat_ref<1, ap_bit_ref, 1, ap_bit_ref<_AP_W2,_AP_S2> >(*this, + const_cast &>(a2)); + } + + + INLINE ap_concat_ref<1, ap_bit_ref, 1, ap_bit_ref > + operator, (const ap_bit_ref &a2) + { + return + ap_concat_ref<1, ap_bit_ref, 1, ap_bit_ref >(*this, + const_cast(a2)); + } + + + template + INLINE ap_concat_ref<1, ap_bit_ref, _AP_W2+_AP_W3, ap_concat_ref<_AP_W2,_AP_T2,_AP_W3,_AP_T3> > + operator, (const ap_concat_ref<_AP_W2,_AP_T2,_AP_W3,_AP_T3> &a2) + { + return + ap_concat_ref<1,ap_bit_ref,_AP_W2+_AP_W3, + ap_concat_ref<_AP_W2,_AP_T2,_AP_W3,_AP_T3> >(*this, + const_cast& >(a2)); + } + + template + INLINE + ap_concat_ref<1, ap_bit_ref, _AP_W2, af_range_ref<_AP_W2, _AP_I2, _AP_S2, _AP_Q2, _AP_O2, _AP_N2> > + operator, (const af_range_ref<_AP_W2, _AP_I2, _AP_S2, _AP_Q2, + _AP_O2, _AP_N2> &a2) { + return ap_concat_ref<1, ap_bit_ref, _AP_W2, af_range_ref<_AP_W2, + _AP_I2, _AP_S2, _AP_Q2, _AP_O2, _AP_N2> >(*this, + const_cast& >(a2)); + } + + template + INLINE + ap_concat_ref<1, ap_bit_ref, 1, af_bit_ref<_AP_W2, _AP_I2, _AP_S2, _AP_Q2, _AP_O2, _AP_N2> > + operator, (const af_bit_ref<_AP_W2, _AP_I2, _AP_S2, _AP_Q2, + _AP_O2, _AP_N2> &a2) { + return ap_concat_ref<1, ap_bit_ref, 1, af_bit_ref<_AP_W2, + _AP_I2, _AP_S2, _AP_Q2, _AP_O2, _AP_N2> >(*this, + const_cast& >(a2)); + } + + template + INLINE bool operator == (const ap_bit_ref<_AP_W2, _AP_S2>& op) { + return get() == op.get(); + } + + template + INLINE bool operator != (const ap_bit_ref<_AP_W2, _AP_S2>& op) { + return get() != op.get(); + } + + + INLINE bool get() const + { + return operator bool (); + } + + + INLINE bool get() + { + return operator bool (); + } + + + template + INLINE void set(const ap_private<_AP_W3, false>& val) + { + operator = (val); + } + + INLINE bool operator ~ () const { + bool bit = (d_bv)[d_index]; + return bit ? false : true; + } + + INLINE int length() const { return 1; } + + INLINE std::string to_string() const { + bool val = get(); + return val ? "1" : "0"; + } +}; + +/// Operators mixing Integers with AP_Int +// ---------------------------------------------------------------- +#if 1 +#define OP_BIN_MIX_INT(BIN_OP, C_TYPE, _AP_WI, _AP_SI, RTYPE) \ + template \ + INLINE typename ap_private<_AP_WI,_AP_SI>::template RType<_AP_W,_AP_S>::RTYPE \ + operator BIN_OP ( C_TYPE i_op, const ap_private<_AP_W,_AP_S> &op) { \ + return ap_private<_AP_WI,_AP_SI>(i_op).operator BIN_OP (op); \ + } \ + template \ + INLINE typename ap_private<_AP_W,_AP_S>::template RType<_AP_WI,_AP_SI>::RTYPE \ + operator BIN_OP ( const ap_private<_AP_W,_AP_S> &op, C_TYPE i_op) { \ + return op.operator BIN_OP (ap_private<_AP_WI,_AP_SI>(i_op)); \ + } +#else +#define OP_BIN_MIX_INT(BIN_OP, C_TYPE, _AP_WI, _AP_SI, RTYPE) \ + template \ + INLINE typename ap_private<_AP_WI,_AP_SI>::template RType<_AP_W,_AP_S>::RTYPE \ + operator BIN_OP ( C_TYPE i_op, const ap_private<_AP_W,_AP_S> &op) { \ + return ap_private<_AP_WI,_AP_SI>(i_op).operator BIN_OP (op); \ + } \ + template \ + INLINE typename ap_private<_AP_W,_AP_S>::template RType<_AP_WI,_AP_SI>::RTYPE \ + operator BIN_OP ( const ap_private<_AP_W,_AP_S> &op, C_TYPE i_op) { \ + return op.operator BIN_OP (ap_private<_AP_WI,_AP_SI>(i_op)); \ + } +#endif +#define OP_REL_MIX_INT(REL_OP, C_TYPE, _AP_W2, _AP_S2) \ + template \ + INLINE bool operator REL_OP ( const ap_private<_AP_W,_AP_S> &op, C_TYPE op2) { \ + return op.operator REL_OP (ap_private<_AP_W2, _AP_S2>(op2)); \ + } \ + template \ + INLINE bool operator REL_OP ( C_TYPE op2, const ap_private<_AP_W,_AP_S> &op) { \ + return ap_private<_AP_W2,_AP_S2>(op2).operator REL_OP (op); \ + } +#define OP_ASSIGN_MIX_INT(ASSIGN_OP, C_TYPE, _AP_W2, _AP_S2) \ + template \ + INLINE ap_private<_AP_W,_AP_S> &operator ASSIGN_OP ( ap_private<_AP_W,_AP_S> &op, C_TYPE op2) { \ + return op.operator ASSIGN_OP (ap_private<_AP_W2,_AP_S2>(op2)); \ + } + +#define OP_BIN_SHIFT_INT(BIN_OP, C_TYPE, _AP_WI, _AP_SI, RTYPE) \ + template \ + C_TYPE operator BIN_OP ( C_TYPE i_op, const ap_private<_AP_W,_AP_S> &op) { \ + return i_op BIN_OP (op.getVal()); \ + } \ + template \ + INLINE typename ap_private<_AP_W,_AP_S>::template RType<_AP_WI,_AP_SI>::RTYPE \ + operator BIN_OP ( const ap_private<_AP_W,_AP_S> &op, C_TYPE i_op) { \ + return op.operator BIN_OP (i_op); \ + } +#define OP_ASSIGN_RSHIFT_INT(ASSIGN_OP, C_TYPE, _AP_W2, _AP_S2) \ + template \ + INLINE ap_private<_AP_W,_AP_S> &operator ASSIGN_OP ( ap_private<_AP_W,_AP_S> &op, C_TYPE op2) { \ + op = op.operator >> (op2); \ + return op; \ + } +#define OP_ASSIGN_LSHIFT_INT(ASSIGN_OP, C_TYPE, _AP_W2, _AP_S2) \ + template \ + INLINE ap_private<_AP_W,_AP_S> &operator ASSIGN_OP ( ap_private<_AP_W,_AP_S> &op, C_TYPE op2) { \ + op = op.operator << (op2); \ + return op; \ + } + +#define OPS_MIX_INT(C_TYPE, WI, SI) \ + OP_BIN_MIX_INT(*, C_TYPE, WI, SI, mult) \ + OP_BIN_MIX_INT(+, C_TYPE, WI, SI, plus) \ + OP_BIN_MIX_INT(-, C_TYPE, WI, SI, minus) \ + OP_BIN_MIX_INT(/, C_TYPE, WI, SI, div) \ + OP_BIN_MIX_INT(%, C_TYPE, WI, SI, mod) \ + OP_BIN_MIX_INT(&, C_TYPE, WI, SI, logic) \ + OP_BIN_MIX_INT(|, C_TYPE, WI, SI, logic) \ + OP_BIN_MIX_INT(^, C_TYPE, WI, SI, logic) \ + OP_BIN_SHIFT_INT(>>, C_TYPE, WI, SI, arg1) \ + OP_BIN_SHIFT_INT(<<, C_TYPE, WI, SI, arg1) \ + \ + OP_REL_MIX_INT(==, C_TYPE, WI, SI) \ + OP_REL_MIX_INT(!=, C_TYPE, WI, SI) \ + OP_REL_MIX_INT(>, C_TYPE, WI, SI) \ + OP_REL_MIX_INT(>=, C_TYPE, WI, SI) \ + OP_REL_MIX_INT(<, C_TYPE, WI, SI) \ + OP_REL_MIX_INT(<=, C_TYPE, WI, SI) \ + \ + OP_ASSIGN_MIX_INT(+=, C_TYPE, WI, SI) \ + OP_ASSIGN_MIX_INT(-=, C_TYPE, WI, SI) \ + OP_ASSIGN_MIX_INT(*=, C_TYPE, WI, SI) \ + OP_ASSIGN_MIX_INT(/=, C_TYPE, WI, SI) \ + OP_ASSIGN_MIX_INT(%=, C_TYPE, WI, SI) \ + OP_ASSIGN_MIX_INT(&=, C_TYPE, WI, SI) \ + OP_ASSIGN_MIX_INT(|=, C_TYPE, WI, SI) \ + OP_ASSIGN_MIX_INT(^=, C_TYPE, WI, SI) \ + OP_ASSIGN_RSHIFT_INT(>>=, C_TYPE, WI, SI) \ + OP_ASSIGN_LSHIFT_INT(<<=, C_TYPE, WI, SI) + + +OPS_MIX_INT(bool, 1, false) +OPS_MIX_INT(char, 8, true) +OPS_MIX_INT(signed char, 8, true) +OPS_MIX_INT(unsigned char, 8, false) +OPS_MIX_INT(short, 16, true) +OPS_MIX_INT(unsigned short, 16, false) +OPS_MIX_INT(int, 32, true) +OPS_MIX_INT(unsigned int, 32, false) +# if defined __x86_64__ +OPS_MIX_INT(long, 64, true) +OPS_MIX_INT(unsigned long, 64, false) +# else +OPS_MIX_INT(long, 32, true) +OPS_MIX_INT(unsigned long, 32, false) +# endif +OPS_MIX_INT(ap_slong, 64, true) +OPS_MIX_INT(ap_ulong, 64, false) + +#define OP_BIN_MIX_RANGE(BIN_OP, RTYPE) \ + template \ + INLINE typename ap_private<_AP_W1,_AP_S1>::template RType<_AP_W2,_AP_S2>::RTYPE \ + operator BIN_OP ( const ap_range_ref<_AP_W1,_AP_S1>& op1, const ap_private<_AP_W2,_AP_S2>& op2) { \ + return ap_private<_AP_W1, false>(op1).operator BIN_OP (op2); \ + } \ + template \ + INLINE typename ap_private<_AP_W1,_AP_S1>::template RType<_AP_W2,_AP_S2>::RTYPE \ + operator BIN_OP ( const ap_private<_AP_W1,_AP_S1>& op1, const ap_range_ref<_AP_W2,_AP_S2>& op2) { \ + return op1.operator BIN_OP (ap_private<_AP_W2, false>(op2)); \ + } + +#define OP_REL_MIX_RANGE(REL_OP) \ + template \ + INLINE bool operator REL_OP ( const ap_range_ref<_AP_W1,_AP_S1>& op1, const ap_private<_AP_W2,_AP_S2>& op2) { \ + return ap_private<_AP_W1,false>(op1).operator REL_OP (op2); \ + } \ + template \ + INLINE bool operator REL_OP ( const ap_private<_AP_W1,_AP_S1>& op1, const ap_range_ref<_AP_W2,_AP_S2>& op2) { \ + return op1.operator REL_OP (op2.operator ap_private<_AP_W2, false>()); \ + } + +#define OP_ASSIGN_MIX_RANGE(ASSIGN_OP) \ + template \ + INLINE ap_private<_AP_W1,_AP_S1>& operator ASSIGN_OP ( ap_private<_AP_W1,_AP_S1>& op1, const ap_range_ref<_AP_W2,_AP_S2>& op2) { \ + return op1.operator ASSIGN_OP (ap_private<_AP_W2, false>(op2)); \ + } \ + template \ + INLINE ap_range_ref<_AP_W1,_AP_S1>& operator ASSIGN_OP (ap_range_ref<_AP_W1,_AP_S1>& op1, ap_private<_AP_W2,_AP_S2>& op2) { \ + ap_private<_AP_W1, false> tmp(op1); \ + tmp.operator ASSIGN_OP (op2); \ + op1 = tmp; \ + return op1; \ + } + + +OP_ASSIGN_MIX_RANGE(+=) +OP_ASSIGN_MIX_RANGE(-=) +OP_ASSIGN_MIX_RANGE(*=) +OP_ASSIGN_MIX_RANGE(/=) +OP_ASSIGN_MIX_RANGE(%=) +OP_ASSIGN_MIX_RANGE(>>=) +OP_ASSIGN_MIX_RANGE(<<=) +OP_ASSIGN_MIX_RANGE(&=) +OP_ASSIGN_MIX_RANGE(|=) +OP_ASSIGN_MIX_RANGE(^=) + +OP_REL_MIX_RANGE(==) +OP_REL_MIX_RANGE(!=) +OP_REL_MIX_RANGE(>) +OP_REL_MIX_RANGE(>=) +OP_REL_MIX_RANGE(<) +OP_REL_MIX_RANGE(<=) + +OP_BIN_MIX_RANGE(+, plus) +OP_BIN_MIX_RANGE(-, minus) +OP_BIN_MIX_RANGE(*, mult) +OP_BIN_MIX_RANGE(/, div) +OP_BIN_MIX_RANGE(%, mod) +OP_BIN_MIX_RANGE(>>, arg1) +OP_BIN_MIX_RANGE(<<, arg1) +OP_BIN_MIX_RANGE(&, logic) +OP_BIN_MIX_RANGE(|, logic) +OP_BIN_MIX_RANGE(^, logic) + +#define OP_BIN_MIX_BIT(BIN_OP, RTYPE) \ + template \ + INLINE typename ap_private<1, false>::template RType<_AP_W2,_AP_S2>::RTYPE \ + operator BIN_OP ( const ap_bit_ref<_AP_W1,_AP_S1>& op1, const ap_private<_AP_W2,_AP_S2>& op2) { \ + return ap_private<1, false>(op1).operator BIN_OP (op2); \ + } \ + template \ + INLINE typename ap_private<_AP_W1,_AP_S1>::template RType<1,false>::RTYPE \ + operator BIN_OP ( const ap_private<_AP_W1,_AP_S1>& op1, const ap_bit_ref<_AP_W2,_AP_S2>& op2) { \ + return op1.operator BIN_OP (ap_private<1, false>(op2)); \ + } + +#define OP_REL_MIX_BIT(REL_OP) \ + template \ + INLINE bool operator REL_OP ( const ap_bit_ref<_AP_W1,_AP_S1>& op1, const ap_private<_AP_W2,_AP_S2>& op2) { \ + return ap_private<_AP_W1,false>(op1).operator REL_OP (op2); \ + } \ + template \ + INLINE bool operator REL_OP ( const ap_private<_AP_W1,_AP_S1>& op1, const ap_bit_ref<_AP_W2,_AP_S2>& op2) { \ + return op1.operator REL_OP (ap_private<1, false>(op2)); \ + } + +#define OP_ASSIGN_MIX_BIT(ASSIGN_OP) \ + template \ + INLINE ap_private<_AP_W1,_AP_S1>& operator ASSIGN_OP ( ap_private<_AP_W1,_AP_S1>& op1, ap_bit_ref<_AP_W2,_AP_S2>& op2) { \ + return op1.operator ASSIGN_OP (ap_private<1, false>(op2)); \ + } \ + template \ + INLINE ap_bit_ref<_AP_W1,_AP_S1>& operator ASSIGN_OP ( ap_bit_ref<_AP_W1,_AP_S1>& op1, ap_private<_AP_W2,_AP_S2>& op2) { \ + ap_private<1, false> tmp(op1); \ + tmp.operator ASSIGN_OP (op2); \ + op1 = tmp; \ + return op1; \ + } + + +OP_ASSIGN_MIX_BIT(+=) +OP_ASSIGN_MIX_BIT(-=) +OP_ASSIGN_MIX_BIT(*=) +OP_ASSIGN_MIX_BIT(/=) +OP_ASSIGN_MIX_BIT(%=) +OP_ASSIGN_MIX_BIT(>>=) +OP_ASSIGN_MIX_BIT(<<=) +OP_ASSIGN_MIX_BIT(&=) +OP_ASSIGN_MIX_BIT(|=) +OP_ASSIGN_MIX_BIT(^=) + +OP_REL_MIX_BIT(==) +OP_REL_MIX_BIT(!=) +OP_REL_MIX_BIT(>) +OP_REL_MIX_BIT(>=) +OP_REL_MIX_BIT(<) +OP_REL_MIX_BIT(<=) + +OP_BIN_MIX_BIT(+, plus) +OP_BIN_MIX_BIT(-, minus) +OP_BIN_MIX_BIT(*, mult) +OP_BIN_MIX_BIT(/, div) +OP_BIN_MIX_BIT(%, mod) +OP_BIN_MIX_BIT(>>, arg1) +OP_BIN_MIX_BIT(<<, arg1) +OP_BIN_MIX_BIT(&, logic) +OP_BIN_MIX_BIT(|, logic) +OP_BIN_MIX_BIT(^, logic) + +#define REF_REL_OP_MIX_INT(REL_OP, C_TYPE, _AP_W2, _AP_S2) \ + template \ + INLINE bool operator REL_OP ( const ap_range_ref<_AP_W,_AP_S> &op, C_TYPE op2) { \ + return (ap_private<_AP_W, false>(op)).operator REL_OP (ap_private<_AP_W2,_AP_S2>(op2)); \ + } \ + template \ + INLINE bool operator REL_OP ( C_TYPE op2, const ap_range_ref<_AP_W,_AP_S> &op) { \ + return ap_private<_AP_W2,_AP_S2>(op2).operator REL_OP (ap_private<_AP_W, false>(op)); \ + } \ + template \ + INLINE bool operator REL_OP ( const ap_bit_ref<_AP_W,_AP_S> &op, C_TYPE op2) { \ + return (bool(op)) REL_OP op2; \ + } \ + template \ + INLINE bool operator REL_OP ( C_TYPE op2, const ap_bit_ref<_AP_W,_AP_S> &op) { \ + return op2 REL_OP (bool(op)); \ + } \ + template \ + INLINE bool operator REL_OP ( const ap_concat_ref<_AP_W,_AP_T, _AP_W1, _AP_T1> &op, C_TYPE op2) { \ + return (ap_private<_AP_W + _AP_W1, false>(op)).operator REL_OP (ap_private<_AP_W2,_AP_S2>(op2)); \ + } \ + template \ + INLINE bool operator REL_OP ( C_TYPE op2, const ap_concat_ref<_AP_W,_AP_T, _AP_W1, _AP_T1> &op) { \ + return ap_private<_AP_W2,_AP_S2>(op2).operator REL_OP (ap_private<_AP_W + _AP_W1, false>(op)); \ + } + +#define REF_REL_MIX_INT(C_TYPE, _AP_WI, _AP_SI) \ +REF_REL_OP_MIX_INT(>, C_TYPE, _AP_WI, _AP_SI) \ +REF_REL_OP_MIX_INT(<, C_TYPE, _AP_WI, _AP_SI) \ +REF_REL_OP_MIX_INT(>=, C_TYPE, _AP_WI, _AP_SI) \ +REF_REL_OP_MIX_INT(<=, C_TYPE, _AP_WI, _AP_SI) \ +REF_REL_OP_MIX_INT(==, C_TYPE, _AP_WI, _AP_SI) \ +REF_REL_OP_MIX_INT(!=, C_TYPE, _AP_WI, _AP_SI) + +REF_REL_MIX_INT(bool, 1, false) +REF_REL_MIX_INT(char, 8, true) +REF_REL_MIX_INT(signed char, 8, true) +REF_REL_MIX_INT(unsigned char, 8, false) +REF_REL_MIX_INT(short, 16, true) +REF_REL_MIX_INT(unsigned short, 16, false) +REF_REL_MIX_INT(int, 32, true) +REF_REL_MIX_INT(unsigned int, 32, false) +# if defined __x86_64__ +REF_REL_MIX_INT(long, 64, true) +REF_REL_MIX_INT(unsigned long, 64, false) +# else +REF_REL_MIX_INT(long, 32, true) +REF_REL_MIX_INT(unsigned long, 32, false) +# endif +REF_REL_MIX_INT(ap_slong, 64, true) +REF_REL_MIX_INT(ap_ulong, 64, false) + +#define REF_BIN_OP_MIX_INT(BIN_OP, RTYPE, C_TYPE, _AP_W2, _AP_S2) \ + template \ + INLINE typename ap_private<_AP_W, false>::template RType<_AP_W2,_AP_S2>::RTYPE \ + operator BIN_OP ( const ap_range_ref<_AP_W,_AP_S> &op, C_TYPE op2) { \ + return (ap_private<_AP_W, false>(op)).operator BIN_OP (ap_private<_AP_W2,_AP_S2>(op2)); \ + } \ + template \ + INLINE typename ap_private<_AP_W2, _AP_S2>::template RType<_AP_W,false>::RTYPE \ + operator BIN_OP ( C_TYPE op2, const ap_range_ref<_AP_W,_AP_S> &op) { \ + return ap_private<_AP_W2,_AP_S2>(op2).operator BIN_OP (ap_private<_AP_W, false>(op)); \ + } + +#define REF_BIN_MIX_INT(C_TYPE, _AP_WI, _AP_SI) \ +REF_BIN_OP_MIX_INT(+, plus, C_TYPE, _AP_WI, _AP_SI) \ +REF_BIN_OP_MIX_INT(-, minus, C_TYPE, _AP_WI, _AP_SI) \ +REF_BIN_OP_MIX_INT(*, mult, C_TYPE, _AP_WI, _AP_SI) \ +REF_BIN_OP_MIX_INT(/, div, C_TYPE, _AP_WI, _AP_SI) \ +REF_BIN_OP_MIX_INT(%, mod, C_TYPE, _AP_WI, _AP_SI) \ +REF_BIN_OP_MIX_INT(>>, arg1, C_TYPE, _AP_WI, _AP_SI) \ +REF_BIN_OP_MIX_INT(<<, arg1, C_TYPE, _AP_WI, _AP_SI) \ +REF_BIN_OP_MIX_INT(&, logic, C_TYPE, _AP_WI, _AP_SI) \ +REF_BIN_OP_MIX_INT(|, logic, C_TYPE, _AP_WI, _AP_SI) \ +REF_BIN_OP_MIX_INT(^, logic, C_TYPE, _AP_WI, _AP_SI) + +REF_BIN_MIX_INT(bool, 1, false) +REF_BIN_MIX_INT(char, 8, true) +REF_BIN_MIX_INT(signed char, 8, true) +REF_BIN_MIX_INT(unsigned char, 8, false) +REF_BIN_MIX_INT(short, 16, true) +REF_BIN_MIX_INT(unsigned short, 16, false) +REF_BIN_MIX_INT(int, 32, true) +REF_BIN_MIX_INT(unsigned int, 32, false) +# if defined __x86_64__ +REF_BIN_MIX_INT(long, 64, true) +REF_BIN_MIX_INT(unsigned long, 64, false) +#else +REF_BIN_MIX_INT(long, 32, true) +REF_BIN_MIX_INT(unsigned long, 32, false) +#endif +REF_BIN_MIX_INT(ap_slong, 64, true) +REF_BIN_MIX_INT(ap_ulong, 64, false) + +#define REF_BIN_OP(BIN_OP, RTYPE) \ +template \ +INLINE typename ap_private<_AP_W, false>::template RType<_AP_W2, false>::RTYPE \ +operator BIN_OP (const ap_range_ref<_AP_W,_AP_S> &lhs, const ap_range_ref<_AP_W2,_AP_S2> &rhs) { \ + return ap_private<_AP_W,false>(lhs).operator BIN_OP (ap_private<_AP_W2, false>(rhs)); \ +} + +REF_BIN_OP(+, plus) +REF_BIN_OP(-, minus) +REF_BIN_OP(*, mult) +REF_BIN_OP(/, div) +REF_BIN_OP(%, mod) +REF_BIN_OP(>>, arg1) +REF_BIN_OP(<<, arg1) +REF_BIN_OP(&, logic) +REF_BIN_OP(|, logic) +REF_BIN_OP(^, logic) + +#if 1 +#define CONCAT_OP_MIX_INT(C_TYPE, _AP_WI, _AP_SI) \ +template \ +INLINE \ +ap_private< _AP_W + _AP_WI, false > \ + operator, (const ap_private<_AP_W, _AP_S> &op1, C_TYPE op2) { \ + ap_private<_AP_WI + _AP_W, false> val(op2); \ + ap_private<_AP_WI + _AP_W, false> ret(op1); \ + ret <<= _AP_WI; \ + if (_AP_SI) { \ + val <<= _AP_W; val >>= _AP_W; \ + }\ + ret |= val; \ + return ret;\ +} \ +template \ +INLINE \ +ap_private< _AP_W + _AP_WI, false > \ + operator, (C_TYPE op1, const ap_private<_AP_W, _AP_S>& op2) { \ + ap_private<_AP_WI + _AP_W, false> val(op1); \ + ap_private<_AP_WI + _AP_W, false> ret(op2); \ + if (_AP_S) { \ + ret <<= _AP_WI; ret >>= _AP_WI; \ + } \ + ret |= val << _AP_W; \ + return ret; \ +} \ +template \ +INLINE \ +ap_private< _AP_W + _AP_WI, false > \ + operator, (const ap_range_ref<_AP_W, _AP_S> &op1, C_TYPE op2) { \ + ap_private<_AP_WI + _AP_W, false> val(op2); \ + ap_private<_AP_WI + _AP_W, false> ret(op1); \ + ret <<= _AP_WI; \ + if (_AP_SI) { \ + val <<= _AP_W; val >>= _AP_W; \ + } \ + ret |= val; \ + return ret; \ +} \ +template \ +INLINE \ +ap_private< _AP_W + _AP_WI, false > \ + operator, (C_TYPE op1, const ap_range_ref<_AP_W, _AP_S> &op2) { \ + ap_private<_AP_WI + _AP_W, false> val(op1); \ + ap_private<_AP_WI + _AP_W, false> ret(op2); \ + int len = op2.length(); \ + val <<= len; \ + ret |= val; \ + return ret; \ +} \ +template \ +INLINE \ +ap_private<_AP_WI + 1, false > \ + operator, (const ap_bit_ref<_AP_W, _AP_S> &op1, C_TYPE op2) { \ + ap_private<_AP_WI + 1, false> val(op2); \ + val[_AP_WI] = op1; \ + return val; \ +} \ +template \ +INLINE \ +ap_private<_AP_WI + 1, false > \ + operator, (C_TYPE op1, const ap_bit_ref<_AP_W, _AP_S> &op2) { \ + ap_private<_AP_WI + 1, false> val(op1); \ + val <<= 1; \ + val[0] = op2; \ + return val; \ +} \ +template \ +INLINE \ +ap_private<_AP_W + _AP_W2 + _AP_WI, false > \ + operator, (const ap_concat_ref<_AP_W, _AP_T, _AP_W2, _AP_T2> &op1, C_TYPE op2) {\ + ap_private<_AP_WI + _AP_W + _AP_W2, _AP_SI> val(op2);\ + ap_private<_AP_WI + _AP_W + _AP_W2, _AP_SI> ret(op1);\ + if (_AP_SI) { \ + val <<= _AP_W + _AP_W2; val >>= _AP_W + _AP_W2; \ + } \ + ret <<= _AP_WI; \ + ret |= val; \ + return ret; \ +}\ +template \ +INLINE \ +ap_private<_AP_W + _AP_W2 + _AP_WI, false > \ + operator, (C_TYPE op1, const ap_concat_ref<_AP_W, _AP_T, _AP_W2, _AP_T2> &op2) {\ + ap_private<_AP_WI + _AP_W + _AP_W2, _AP_SI> val(op1);\ + ap_private<_AP_WI + _AP_W + _AP_W2, _AP_SI> ret(op2);\ + int len = op2.length(); \ + val <<= len; \ + ret |= val;\ + return ret; \ +}\ +template \ +INLINE \ +ap_private< _AP_W + _AP_WI, false > \ + operator, (const af_range_ref<_AP_W, _AP_I, _AP_S, _AP_Q, _AP_O, _AP_N> &op1, C_TYPE op2) { \ + ap_private<_AP_WI + _AP_W, false> val(op2); \ + ap_private<_AP_WI + _AP_W, false> ret(op1); \ + if (_AP_SI) { \ + val <<= _AP_W; val >>= _AP_W; \ + }\ + ret <<= _AP_WI; \ + ret |= val; \ + return ret; \ +} \ +template \ +INLINE \ +ap_private< _AP_W + _AP_WI, false > \ + operator, (C_TYPE op1, const af_range_ref<_AP_W, _AP_I, _AP_S, \ + _AP_Q, _AP_O, _AP_N> &op2) { \ + ap_private<_AP_WI + _AP_W, false> val(op1); \ + ap_private<_AP_WI + _AP_W, false> ret(op2); \ + int len = op2.length(); \ + val <<= len; \ + ret |= val; \ + return ret; \ +} \ +template \ +INLINE \ +ap_private< 1 + _AP_WI, false> \ + operator, (const af_bit_ref<_AP_W, _AP_I, _AP_S, _AP_Q, _AP_O, \ + _AP_N> &op1, C_TYPE op2) { \ + ap_private<_AP_WI + 1, _AP_SI> val(op2); \ + val[_AP_WI] = op1; \ + return val; \ +} \ +template \ +INLINE \ +ap_private< 1 + _AP_WI, false> \ + operator, (C_TYPE op1, const af_bit_ref<_AP_W, _AP_I, _AP_S, _AP_Q,\ + _AP_O, _AP_N> &op2) { \ + ap_private<_AP_WI + 1, _AP_SI> val(op1); \ + val <<= 1; \ + val[0] = op2; \ + return val; \ +} + +CONCAT_OP_MIX_INT(bool, 1, false) +CONCAT_OP_MIX_INT(char, 8, true) +CONCAT_OP_MIX_INT(signed char, 8, true) +CONCAT_OP_MIX_INT(unsigned char, 8, false) +CONCAT_OP_MIX_INT(short, 16, true) +CONCAT_OP_MIX_INT(unsigned short, 16, false) +CONCAT_OP_MIX_INT(int, 32, true) +CONCAT_OP_MIX_INT(unsigned int, 32, false) +# if defined __x86_64__ +CONCAT_OP_MIX_INT(long, 64, true) +CONCAT_OP_MIX_INT(unsigned long, 64, false) +# else +CONCAT_OP_MIX_INT(long, 32, true) +CONCAT_OP_MIX_INT(unsigned long, 32, false) +# endif +CONCAT_OP_MIX_INT(ap_slong, 64, true) +CONCAT_OP_MIX_INT(ap_ulong, 64, false) +#endif + +#if 1 +#define CONCAT_SHIFT_MIX_INT(C_TYPE, op) \ +template \ +INLINE ap_uint<_AP_W+_AP_W1> operator op (const ap_concat_ref<_AP_W, _AP_T, _AP_W1, _AP_T1> lhs, C_TYPE rhs) { \ + return ((ap_uint<_AP_W+_AP_W1>)lhs.get()) op ((int)rhs); \ +} + +CONCAT_SHIFT_MIX_INT(long, <<) +CONCAT_SHIFT_MIX_INT(unsigned long, <<) +CONCAT_SHIFT_MIX_INT(unsigned int, <<) +CONCAT_SHIFT_MIX_INT(ap_ulong, <<) +CONCAT_SHIFT_MIX_INT(ap_slong, <<) +CONCAT_SHIFT_MIX_INT(long, >>) +CONCAT_SHIFT_MIX_INT(unsigned long, >>) +CONCAT_SHIFT_MIX_INT(unsigned int, >>) +CONCAT_SHIFT_MIX_INT(ap_ulong, >>) +CONCAT_SHIFT_MIX_INT(ap_slong, >>) +#endif + +#if defined(SYSTEMC_H) || defined(SYSTEMC_INCLUDED) +template +INLINE void sc_trace(sc_core::sc_trace_file *tf, const ap_private<_AP_W, _AP_S> &op, + const std::string &name) { + if (tf) + tf->trace(sc_dt::sc_lv<_AP_W>(op.to_string(2).c_str()), name); +} +#endif + +template +INLINE std::ostream& operator<<(std::ostream& out, const ap_private<_AP_W,_AP_S> &op) +{ + ap_private<_AP_W, _AP_S> v=op; + const std::ios_base::fmtflags basefield = out.flags() & std::ios_base::basefield; + unsigned radix = (basefield == std::ios_base::hex) ? 16 : + ((basefield == std::ios_base::oct) ? 8 : 10); + std::string str=v.toString(radix,_AP_S); + out< +INLINE std::istream& operator >> (std::istream& in, ap_private<_AP_W,_AP_S> &op) +{ + std::string str; + in >> str; + op = ap_private<_AP_W, _AP_S>(str.c_str()); + return in; + +} + +template +INLINE std::ostream& operator<<(std::ostream& out, const ap_range_ref<_AP_W,_AP_S> &op) +{ + return operator<<(out, ap_private<_AP_W, _AP_S>(op)); +} + +template +INLINE std::istream& operator >> (std::istream& in, ap_range_ref<_AP_W,_AP_S> &op) +{ + return operator>>(in, ap_private<_AP_W, _AP_S>(op));; +} + +template +INLINE void print(const ap_private<_AP_W,_AP_S> &op, bool fill=true ) +{ + ap_private<_AP_W, _AP_S> v=op; + uint32_t ws=v.getNumWords(); + const uint64_t *ptr=v.getRawData(); + int i=ws-1; +#if 0 + if(fill) + printf("%016llx",*(ptr+i)); + else + printf("%llx",*(ptr+i)); +#else +//match SystemC output + if(_AP_W%64 != 0) { + uint32_t offset=_AP_W%64; + uint32_t count=(offset+3)/4; + int64_t data=*(ptr+i); + if(_AP_S) + data=(data<<(64-offset))>>(64-offset); + else + count=(offset+4)/4; + while(count-->0) + printf("%llx",(data>>(count*4))&0xf); + } else { + if(_AP_S==false) + printf("0"); + printf("%016llx",*(ptr+i)); + } +#endif + for(--i;i>=0;i--) + printf("%016llx",*(ptr+i)); + printf("\n"); + +} +#endif /* #ifndef __AESL_GCC_AP_INT_H__ */ \ No newline at end of file diff --git a/router/etc/ap_private.h b/router/etc/ap_private.h new file mode 100644 index 0000000..1a68a9e --- /dev/null +++ b/router/etc/ap_private.h @@ -0,0 +1,5858 @@ +/* + * Copyright 2012 Xilinx, Inc. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef LLVM_SUPPORT_MATHEXTRAS_H +#define LLVM_SUPPORT_MATHEXTRAS_H + +#ifdef _MSC_VER +#if _MSC_VER <= 1500 +typedef __int8 int8_t; +typedef unsigned __int8 uint8_t; +typedef __int16 int16_t; +typedef unsigned __int16 uint16_t; +typedef __int32 int32_t; +typedef unsigned __int32 uint32_t; +typedef __int64 int64_t; +typedef unsigned __int64 uint64_t; +#else if +#include +#endif /* #if _MSC_VER <= 1500 */ +#else +#include +#endif /* #if _MSC_VER <= 1500 */ +#undef INLINE +#if 1 +#define INLINE inline +#else +//Enable to debug ap_int/ap_fixed +#define INLINE __attribute__((weak)) +#endif +#define AP_MAX(a,b) ((a) > (b) ? (a) : (b)) +#define AP_MIN(a,b) ((a) < (b) ? (a) : (b)) +#define AP_ABS(a) ((a)>=0 ? (a):-(a)) +#ifndef AP_INT_MAX_W +#define AP_INT_MAX_W 1024 +#endif +#define BIT_WIDTH_UPPER_LIMIT (1 << 15) +#if AP_INT_MAX_W > BIT_WIDTH_UPPER_LIMIT +#error "Bitwidth exceeds 32768 (1 << 15), the maximum allowed value" +#endif +#define MAX_MODE(BITS) ((BITS + 1023) / 1024) + +// NOTE: The following support functions use the _32/_64 extensions instead of +// type overloading so that signed and unsigned integers can be used without +// ambiguity. + +/// Hi_32 - This function returns the high 32 bits of a 64 bit value. +INLINE uint32_t Hi_32(uint64_t Value) { + return static_cast(Value >> 32); +} + +/// Lo_32 - This function returns the low 32 bits of a 64 bit value. +INLINE uint32_t Lo_32(uint64_t Value) { + return static_cast(Value); +} + +/// ByteSwap_16 - This function returns a byte-swapped representation of the +/// 16-bit argument, Value. +INLINE uint16_t ByteSwap_16(uint16_t Value) { +#if defined(_MSC_VER) && !defined(_DEBUG) + // The DLL version of the runtime lacks these functions (bug!?), but in a + // release build they're replaced with BSWAP instructions anyway. + return (uint16_t)(_byteswap_ushort(Value)); +#else + uint16_t Hi = (uint16_t)((Value) << 8); + uint16_t Lo = (uint16_t)((Value) >> 8); + return Hi | Lo; +#endif +} + +/// ByteSwap_32 - This function returns a byte-swapped representation of the +/// 32-bit argument, Value. +INLINE uint32_t ByteSwap_32(uint32_t Value) { + uint32_t Byte0 = Value & 0x000000FF; + uint32_t Byte1 = Value & 0x0000FF00; + uint32_t Byte2 = Value & 0x00FF0000; + uint32_t Byte3 = Value & 0xFF000000; + return ((Byte0) << 24) | ((Byte1) << 8) | ((Byte2) >> 8) | ((Byte3) >> 24); +} + +/// ByteSwap_64 - This function returns a byte-swapped representation of the +/// 64-bit argument, Value. +INLINE uint64_t ByteSwap_64(uint64_t Value) { + uint64_t Hi = ByteSwap_32(uint32_t(Value)); + uint32_t Lo = ByteSwap_32(uint32_t(Value >> 32)); + return ((Hi) << 32) | Lo; +} + +/// CountLeadingZeros_32 - this function performs the platform optimal form of +/// counting the number of zeros from the most significant bit to the first one +/// bit. Ex. CountLeadingZeros_32(0x00F000FF) == 8. +/// Returns 32 if the word is zero. +INLINE unsigned CountLeadingZeros_32(uint32_t Value) { + unsigned Count; // result +#if __GNUC__ >= 4 + // PowerPC is defined for __builtin_clz(0) +#if !defined(__ppc__) && !defined(__ppc64__) + if (Value == 0) return 32; +#endif + Count = __builtin_clz(Value); +#else + if (Value == 0) return 32; + Count = 0; + // bisecton method for count leading zeros + for (unsigned Shift = 32 >> 1; Shift; Shift >>= 1) { + uint32_t Tmp = (Value) >> (Shift); + if (Tmp) { + Value = Tmp; + } else { + Count |= Shift; + } + } +#endif + return Count; +} + +/// CountLeadingZeros_64 - This function performs the platform optimal form +/// of counting the number of zeros from the most significant bit to the first +/// one bit (64 bit edition.) +/// Returns 64 if the word is zero. +INLINE unsigned CountLeadingZeros_64(uint64_t Value) { + unsigned Count; // result +#if __GNUC__ >= 4 + // PowerPC is defined for __builtin_clzll(0) +#if !defined(__ppc__) && !defined(__ppc64__) + if (!Value) return 64; +#endif + Count = __builtin_clzll(Value); +#else + if (sizeof(long) == sizeof(int64_t)) { + if (!Value) return 64; + Count = 0; + // bisecton method for count leading zeros + for (unsigned Shift = 64 >> 1; Shift; Shift >>= 1) { + uint64_t Tmp = (Value) >> (Shift); + if (Tmp) { + Value = Tmp; + } else { + Count |= Shift; + } + } + } else { + // get hi portion + uint32_t Hi = Hi_32(Value); + + // if some bits in hi portion + if (Hi) { + // leading zeros in hi portion plus all bits in lo portion + Count = CountLeadingZeros_32(Hi); + } else { + // get lo portion + uint32_t Lo = Lo_32(Value); + // same as 32 bit value + Count = CountLeadingZeros_32(Lo)+32; + } + } +#endif + return Count; +} + +/// CountTrailingZeros_64 - This function performs the platform optimal form +/// of counting the number of zeros from the least significant bit to the first +/// one bit (64 bit edition.) +/// Returns 64 if the word is zero. +INLINE unsigned CountTrailingZeros_64(uint64_t Value) { +#if __GNUC__ >= 4 + return (Value != 0) ? __builtin_ctzll(Value) : 64; +#else + static const unsigned Mod67Position[] = { + 64, 0, 1, 39, 2, 15, 40, 23, 3, 12, 16, 59, 41, 19, 24, 54, + 4, 64, 13, 10, 17, 62, 60, 28, 42, 30, 20, 51, 25, 44, 55, + 47, 5, 32, 65, 38, 14, 22, 11, 58, 18, 53, 63, 9, 61, 27, + 29, 50, 43, 46, 31, 37, 21, 57, 52, 8, 26, 49, 45, 36, 56, + 7, 48, 35, 6, 34, 33, 0 + }; + return Mod67Position[(uint64_t)(-(int64_t)Value & (int64_t)Value) % 67]; +#endif +} + +/// CountPopulation_64 - this function counts the number of set bits in a value, +/// (64 bit edition.) +INLINE unsigned CountPopulation_64(uint64_t Value) { +#if __GNUC__ >= 4 + return __builtin_popcountll(Value); +#else + uint64_t v = Value - (((Value) >> 1) & 0x5555555555555555ULL); + v = (v & 0x3333333333333333ULL) + (((v) >> 2) & 0x3333333333333333ULL); + v = (v + ((v) >> 4)) & 0x0F0F0F0F0F0F0F0FULL; + return unsigned((uint64_t)(v * 0x0101010101010101ULL) >> 56); +#endif +} + +#endif // LLVM_SUPPORT_MATHEXTRAS_H + + +#ifndef AP_PRIVATE_H +#define AP_PRIVATE_H + +#include +#include +#include +#include +#include +#include +#include +#include + +namespace AESL_std { + template + DataType INLINE min(DataType a, DataType b) { + // if (a >= b) return b; + // else return a; + return (a>=b) ? b : a; + } + + template + DataType INLINE max(DataType a, DataType b) { + // if (a >= b) return a; + // else return b; + return (a>=b) ? a : b; + } +} +enum ap_q_mode { + AP_RND, // rounding to plus infinity + AP_RND_ZERO,// rounding to zero + AP_RND_MIN_INF,// rounding to minus infinity + AP_RND_INF,// rounding to infinity + AP_RND_CONV, // convergent rounding + AP_TRN, // truncation + AP_TRN_ZERO // truncation to zero + +}; +enum ap_o_mode { + AP_SAT, // saturation + AP_SAT_ZERO, // saturation to zero + AP_SAT_SYM, // symmetrical saturation + AP_WRAP, // wrap-around (*) + AP_WRAP_SM // sign magnitude wrap-around (*) +}; + +template struct ap_fixed_base; +template struct af_range_ref; +template struct af_bit_ref; + +template struct ap_range_ref; +template struct ap_bit_ref; +template struct ap_concat_ref; +static bool InvalidDigit(const char* str, unsigned len, unsigned start, unsigned radix) { + unsigned i; + for (i = start; i < len; ++i) + if ((radix == 2 && (str[i] == '0' || str[i] == '1')) || + (radix == 8 && str[i] >= '0' && str[i] <= '7') || + (radix == 10 && str[i] >= '0' && str[i] <= '9') || + (radix == 16 && ((str[i] >= '0' && str[i] <= '9') || + (str[i] >= 'a' && str[i] <= 'f') || + (str[i] >= 'A' && str[i] <= 'F')))) + continue; + else + return true; + return false; +} + +static void ap_parse_sign(const char* str, uint32_t &base, bool &neg) { + if (str[0] == '+' || str[0] == '-') base = 1; + if (str[0] == '-') neg = true; + else neg = false; + return; +} + +static void ap_parse_prefix(const char* str, uint32_t &offset, uint32_t &radix) { + if (str[0] == '0') { + switch (str[1]) { + case 'b': + case 'B': offset = 2; radix = 2; break; + case 'x': + case 'X': offset = 2; radix = 16; break; + case 'd': + case 'D': offset = 2; radix = 10; break; + case 'o': + case 'O': offset = 2; radix = 8; break; + default: break; + } + } + if (offset == 0) + for (int i=0, len = strlen(str); i= 'a') || (str[i] <= 'F' && str[i] >= 'A')) { + radix = 16; + break; + } + return; +} + +/// sub_1 - This function subtracts a single "digit" (64-bit word), y, from +/// the multi-digit integer array, x[], propagating the borrowed 1 value until +/// no further borrowing is neeeded or it runs out of "digits" in x. The result +/// is 1 if "borrowing" exhausted the digits in x, or 0 if x was not exhausted. +/// In other words, if y > x then this function returns 1, otherwise 0. +/// @returns the borrow out of the subtraction +static bool sub_1(uint64_t x[], uint32_t len, uint64_t y) { + for (uint32_t i = 0; i < len; ++i) { + uint64_t __X = x[i]; + x[i] -= y; + if (y > __X) + y = 1; // We have to "borrow 1" from next "digit" + else { + y = 0; // No need to borrow + break; // Remaining digits are unchanged so exit early + } + } + return (y != 0); +} + + /// This enumeration just provides for internal constants used in this + /// translation unit. + enum { + MIN_INT_BITS = 1, ///< Minimum number of bits that can be specified + ///< Note that this must remain synchronized with IntegerType::MIN_INT_BITS + MAX_INT_BITS = (1<<23)-1 ///< Maximum number of bits that can be specified + ///< Note that this must remain synchronized with IntegerType::MAX_INT_BITS + }; + + /// A utility function for allocating memory and checking for allocation + /// failure. The content is not zeroed. + static uint64_t* getMemory(uint32_t numWords) { + return (uint64_t*) malloc(numWords*sizeof(uint64_t)); + } + + //===----------------------------------------------------------------------===// + // ap_private Class + //===----------------------------------------------------------------------===// + + /// ap_private - This class represents arbitrary precision constant integral values. + /// It is a functional replacement for common case unsigned integer type like + /// "unsigned", "unsigned long" or "uint64_t", but also allows non-byte-width + /// integer sizes and large integer value types such as 3-bits, 15-bits, or more + /// than 64-bits of precision. ap_private provides a variety of arithmetic operators + /// and methods to manipulate integer values of any bit-width. It supports both + /// the typical integer arithmetic and comparison operations as well as bitwise + /// manipulation. + /// + /// The class has several invariants worth noting: + /// * All bit, byte, and word positions are zero-based. + /// * Once the bit width is set, it doesn't change except by the Truncate, + /// SignExtend, or ZeroExtend operations. + /// * All binary operators must be on ap_private instances of the same bit width. + /// Attempting to use these operators on instances with different bit + /// widths will yield an assertion. + /// * The value is stored canonically as an unsigned value. For operations + /// where it makes a difference, there are both signed and unsigned variants + /// of the operation. For example, sdiv and udiv. However, because the bit + /// widths must be the same, operations such as Mul and Add produce the same + /// results regardless of whether the values are interpreted as signed or + /// not. + /// * In general, the class tries to follow the style of computation that LLVM + /// uses in its IR. This simplifies its use for LLVM. + /// + /// @brief Class for arbitrary precision integers. + template class ap_private; + namespace ap_private_ops{ + template + INLINE ap_private<_AP_W, _AP_S, _AP_N> lshr(const ap_private<_AP_W, _AP_S, _AP_N>& LHS, uint32_t shiftAmt); + template + INLINE ap_private<_AP_W, _AP_S, _AP_N> shl(const ap_private<_AP_W, _AP_S, _AP_N>& LHS, uint32_t shiftAmt); + } + +#if defined(_MSC_VER) +# if _MSC_VER < 1400 && !defined(for) +# define for if(0);else for +# endif + typedef unsigned __int64 ap_ulong; + typedef signed __int64 ap_slong; +#else + typedef unsigned long long ap_ulong; + typedef signed long long ap_slong; +#endif + template struct retval { + }; + template<> struct retval { + typedef ap_slong Type; + }; + template<> struct retval { + typedef ap_ulong Type; + }; + + template + class ap_private { +#ifdef _MSC_VER +#pragma warning( disable : 4521 4522 ) +#endif +public: + typedef typename retval<_AP_S>::Type ValType; + template friend struct ap_fixed_base; + ///return type of variety of operations + //---------------------------------------------------------- + template + struct RType { + enum { + mult_w = _AP_W+_AP_W2, + mult_s = _AP_S||_AP_S2, + plus_w = AP_MAX(_AP_W+(_AP_S2&&!_AP_S),_AP_W2+(_AP_S&&!_AP_S2))+1, + plus_s = _AP_S||_AP_S2, + minus_w = AP_MAX(_AP_W+(_AP_S2&&!_AP_S),_AP_W2+(_AP_S&&!_AP_S2))+1, + minus_s = true, + div_w = _AP_W+_AP_S2, + div_s = _AP_S||_AP_S2, + mod_w = AP_MIN(_AP_W,_AP_W2+(!_AP_S2&&_AP_S)), + mod_s = _AP_S, + logic_w = AP_MAX(_AP_W+(_AP_S2&&!_AP_S),_AP_W2+(_AP_S&&!_AP_S2)), + logic_s = _AP_S||_AP_S2 + }; + typedef ap_private mult; + typedef ap_private plus; + typedef ap_private minus; + typedef ap_private logic; + typedef ap_private div; + typedef ap_private mod; + typedef ap_private<_AP_W, _AP_S> arg1; + typedef bool reduce; + }; + + INLINE void report() { +#if 0 + if (_AP_W > 1024 && _AP_W <= 4096) { + fprintf(stderr, "[W] W=%d is out of bound (1<=W<=1024): for" + " synthesis: please define macro AP_INT_TYPE_EXT(N)" + " to extend the valid range.\n", _AP_W); + } else +#endif + if (_AP_W > MAX_MODE(AP_INT_MAX_W) * 1024) { + fprintf(stderr, "[E] ap_%sint<%d>: Bitwidth exceeds the " + "default max value %d. Please use macro " + "AP_INT_MAX_W to set a larger max value.\n", + _AP_S?"":"u", _AP_W, + MAX_MODE(AP_INT_MAX_W) * 1024); + exit(1); + } + } + + enum { BitWidth = _AP_W }; + /// This union is used to store the integer value. When the + /// integer bit-width <= 64, it uses VAL, otherwise it uses pVal. + + /// This enum is used to hold the constants we needed for ap_private. + uint64_t VAL; ///< Used to store the <= 64 bits integer value. + uint64_t pVal[_AP_N]; ///< Used to store the >64 bits integer value. + + /// This enum is used to hold the constants we needed for ap_private. + enum { + APINT_BITS_PER_WORD = sizeof(uint64_t) * 8, ///< Bits in a word + APINT_WORD_SIZE = sizeof(uint64_t) ///< Byte size of a word + }; + + enum { excess_bits = (_AP_W%APINT_BITS_PER_WORD) ? APINT_BITS_PER_WORD -(_AP_W%APINT_BITS_PER_WORD) : 0}; + static const uint64_t mask = ((uint64_t)~0ULL >> (excess_bits)); + + /// This constructor is used only internally for speed of construction of + /// temporaries. It is unsafe for general use so it is not public. + /* Constructors */ + + ap_private(const char* val) { + std::string str(val); + uint32_t strLen = str.length(); + const char *strp = str.c_str(); + uint32_t offset = 0; + uint32_t base = 0; + bool neg = false; + uint32_t radix = 16; + ap_parse_sign(strp, base, neg); + ap_parse_prefix(strp + base, offset, radix); + + if ((radix != 10 && neg) || + (strLen - base - offset <= 0) || + InvalidDigit(strp, strLen, base + offset, radix)) { + fprintf(stderr, "invalid character string %s !\n", val); + assert(0); + } + + ap_private ap_private_val(str.c_str(), strLen, radix, base, offset); + if (neg) + ap_private_val = -ap_private_val; + operator = (ap_private_val); + report(); + } + + ap_private(const char* val, int rd) { + std::string str(val); + uint32_t strLen = str.length(); + const char *strp = str.c_str(); + uint32_t offset = 0; + uint32_t base = 0; + uint32_t radix = rd; + bool neg = false; + ap_parse_sign(strp, base, neg); + ap_parse_prefix(strp + base, offset, radix); + + if ((radix != 10 && neg) || + (strLen - base - offset <= 0) || + InvalidDigit(strp, strLen, base + offset, radix)) { + fprintf(stderr, "invalid character string %s !\n", val); + assert(0); + } + + // uint32_t bitsNeeded = ap_private<_AP_W, _AP_S>::getBitsNeeded(strp, strLen, radix); + // ap_private<_AP_W, _AP_S> ap_private_val(bitsNeeded, strp , strLen, radix, base, offset); + ap_private ap_private_val(strp , strLen, radix, base, offset); + if (neg) + ap_private_val = -ap_private_val; + operator = (ap_private_val); + report(); + } + + /// Note that numWords can be smaller or larger than the corresponding bit + /// width but any extraneous bits will be dropped. + /// @param numBits the bit width of the constructed ap_private + /// @param numWords the number of words in bigVal + /// @param bigVal a sequence of words to form the initial value of the ap_private + /// @brief Construct an ap_private of numBits width, initialized as bigVal[]. + ap_private(uint32_t numWords, const uint64_t bigVal[]): VAL(0) { + assert(bigVal && "Null pointer detected!"); + { + // Get memory, cleared to 0 + memset(pVal, 0, _AP_N * sizeof(uint64_t)); + + // Calculate the number of words to copy + uint32_t words = AESL_std::min(numWords, _AP_N); + // Copy the words from bigVal to pVal + memcpy(pVal, bigVal, words * APINT_WORD_SIZE); + if (words >= _AP_W) + clearUnusedBits(); + // Make sure unused high bits are cleared + } + } + + /// This constructor interprets Val as a string in the given radix. The + /// interpretation stops when the first charater that is not suitable for the + /// radix is encountered. Acceptable radix values are 2, 8, 10 and 16. It is + /// an error for the value implied by the string to require more bits than + /// numBits. + /// @param numBits the bit width of the constructed ap_private + /// @param val the string to be interpreted + /// @param radix the radix of Val to use for the intepretation + /// @brief Construct an ap_private from a string representation. + ap_private(const std::string& val, uint8_t radix=2, int base=0, int offset=0): VAL(0) { + assert(!val.empty() && "The input string is empty."); + const char *c_str = val.c_str(); + fromString(c_str+base+offset, val.size()-base-offset, radix); + } + + /// This constructor interprets the slen characters starting at StrStart as + /// a string in the given radix. The interpretation stops when the first + /// character that is not suitable for the radix is encountered. Acceptable + /// radix values are 2, 8, 10 and 16. It is an error for the value implied by + /// the string to require more bits than numBits. + /// @param numBits the bit width of the constructed ap_private + /// @param strStart the start of the string to be interpreted + /// @param slen the maximum number of characters to interpret + /// @param radix the radix to use for the conversion + /// @brief Construct an ap_private from a string representation. + /// This method does not consider whether it is negative or not. + ap_private(const char strStart[], uint32_t slen, uint8_t radix, int base=0, int offset=0) : VAL(0) { + fromString(strStart+base+offset, slen-base-offset, radix); + } + + template + INLINE ap_private(const ap_range_ref<_AP_W2,_AP_S2>& ref) { + *this=ref.get(); + report(); + } + + template + INLINE ap_private(const ap_bit_ref<_AP_W2,_AP_S2>& ref) { + *this = ((uint64_t)(bool)ref); + report(); + } + + template + INLINE ap_private(const ap_concat_ref<_AP_W2, _AP_T2,_AP_W3, _AP_T3>& ref) { + *this=ref.get(); + report(); + } + + template + INLINE ap_private(const af_range_ref<_AP_W2, _AP_I2, _AP_S2, + _AP_Q2, _AP_O2, _AP_N2> &val) { + *this = ((val.operator ap_private<_AP_W2, false> ())); + report(); + } + + template + INLINE ap_private(const af_bit_ref<_AP_W2, _AP_I2, _AP_S2, + _AP_Q2, _AP_O2, _AP_N2> &val) { + *this = (uint64_t)(bool)val; + report(); + } + + /// Simply makes *this a copy of that. + /// @brief Copy Constructor. + template + ap_private(const volatile ap_private<_AP_W1, _AP_S1, _AP_N1>& that): VAL(0) { + operator = (const_cast& >(that)); + } + + template + ap_private(const ap_private<_AP_W1, _AP_S1, _AP_N1>& that): VAL(0) { + operator = (that); + } + + template + explicit ap_private(const ap_private<_AP_W1, _AP_S1, 1>& that): VAL(0) { + static const uint64_t that_sign_ext_mask = (_AP_W1==APINT_BITS_PER_WORD)?0:~0ULL>>(_AP_W1%APINT_BITS_PER_WORD)<<(_AP_W1%APINT_BITS_PER_WORD); + if (that.isNegative()) { + pVal[0] = that.VAL|that_sign_ext_mask; + memset(pVal+1, ~0, sizeof(uint64_t)*(_AP_N-1)); + } else { + pVal[0] = that.VAL; + memset(pVal+1, 0, sizeof(uint64_t)*(_AP_N-1)); + } + clearUnusedBits(); + } + + ap_private(const ap_private& that): VAL(0) { + memcpy(pVal, that.pVal, _AP_N * APINT_WORD_SIZE); + clearUnusedBits(); + } + + /// @brief Destructor. + virtual ~ap_private() {} + + /// Default constructor that creates an uninitialized ap_private. This is useful + /// for object deserialization (pair this with the static method Read). + ap_private(){memset(pVal, 0, sizeof(uint64_t)*(_AP_N));} + + ap_private(uint64_t* val, uint32_t bits=_AP_W) {assert(0);} + ap_private(const uint64_t *const val, uint32_t bits) {assert(0);} + + /// @name Constructors + /// @{ + /// If isSigned is true then val is treated as if it were a signed value + /// (i.e. as an int64_t) and the appropriate sign extension to the bit width + /// will be done. Otherwise, no sign extension occurs (high order bits beyond + /// the range of val are zero filled). + /// @param numBits the bit width of the constructed ap_private + /// @param val the initial value of the ap_private + /// @param isSigned how to treat signedness of val + /// @brief Create a new ap_private of numBits width, initialized as val. +#define CTOR(TYPE, SIGNED) \ + ap_private(TYPE val, bool isSigned=SIGNED) { \ + pVal[0] = val; \ + if (isSigned && int64_t(pVal[0]) < 0) { \ + memset(pVal+1, ~0, sizeof(uint64_t)*(_AP_N-1)); \ + } else { \ + memset(pVal+1, 0, sizeof(uint64_t)*(_AP_N-1)); \ + } \ + clearUnusedBits(); \ + } +#if 1 + CTOR(int, true) + CTOR(bool, false) + CTOR(signed char, true) + CTOR(unsigned char, false) + CTOR(short, true) + CTOR(unsigned short, false) + CTOR(unsigned int, false) + CTOR(long, true) + CTOR(unsigned long, false) + CTOR(unsigned long long, false) + CTOR(long long, true) + CTOR(float, false) + CTOR(double, false) +#undef CTOR +#else + CTOR(uint64_t) +#undef CTOR +#endif + + + /// @returns true if the number of bits <= 64, false otherwise. + /// @brief Determine if this ap_private just has one word to store value. + INLINE bool isSingleWord() const { + return false; + } + + /// @returns the word position for the specified bit position. + /// @brief Determine which word a bit is in. + static uint32_t whichWord(uint32_t bitPosition) { + // return bitPosition / APINT_BITS_PER_WORD; + return (bitPosition) >> 6; + } + + /// @returns the bit position in a word for the specified bit position + /// in the ap_private. + /// @brief Determine which bit in a word a bit is in. + static uint32_t whichBit(uint32_t bitPosition) { + // return bitPosition % APINT_BITS_PER_WORD; + return bitPosition & 0x3f; + } + + /// bit at a specific bit position. This is used to mask the bit in the + /// corresponding word. + /// @returns a uint64_t with only bit at "whichBit(bitPosition)" set + /// @brief Get a single bit mask. + static uint64_t maskBit(uint32_t bitPosition) { + return 1ULL << (whichBit(bitPosition)); + } + + /// @returns the corresponding word for the specified bit position. + /// @brief Get the word corresponding to a bit position + INLINE uint64_t getWord(uint32_t bitPosition) const { + return isSingleWord() ? VAL : pVal[whichWord(bitPosition)]; + } + + /// This method is used internally to clear the to "N" bits in the high order + /// word that are not used by the ap_private. This is needed after the most + /// significant word is assigned a value to ensure that those bits are + /// zero'd out. + /// @brief Clear unused high order bits + INLINE void clearUnusedBits(void) { + pVal[_AP_N-1] = _AP_S ? ((((int64_t)pVal[_AP_N-1])<<(excess_bits))>> excess_bits) : (excess_bits ? ((pVal[_AP_N-1])<<(excess_bits))>>(excess_bits) : pVal[_AP_N-1]); + } + + INLINE void clearUnusedBitsToZero(void) { + pVal[_AP_N-1] &= mask; + } + + INLINE void clearUnusedBitsToOne(void) { + pVal[_AP_N-1] |= mask; + } + + /// This is used by the constructors that take string arguments. + /// @brief Convert a char array into an ap_private + INLINE void fromString(const char *strStart, uint32_t slen, + uint8_t radix) ; + + INLINE ap_private read() volatile { + return *this; + } + + INLINE void write(const ap_private& op2) volatile { + *this = (op2); + } + + //Explicit conversions to C interger types + //----------------------------------------------------------- + operator ValType() const { + return getVal(); + } + + INLINE ValType getVal() const{ + return *pVal; + } + + INLINE int to_int() const { + return int(*this); + } + + INLINE unsigned to_uint() const { + return (unsigned) getVal(); + } + + INLINE long to_long() const { + return (long) getVal(); + } + + INLINE unsigned long to_ulong() const { + return (unsigned long) getVal(); + } + + INLINE ap_slong to_int64() const { + return (ap_slong) getVal(); + } + + INLINE ap_ulong to_uint64() const { + return (ap_ulong) getVal(); + } + + INLINE double to_double() const { + if (isNegative()) + return roundToDouble(true); + else + return roundToDouble(false); + } + + INLINE unsigned length() const { return _AP_W; } + + /*Reverse the contents of ap_private instance. I.e. LSB becomes MSB and vise versa*/ + INLINE ap_private& reverse () { + for (int i = 0; i < _AP_W/2; ++i) { + bool tmp = operator[](i); + if (operator[](_AP_W - 1 - i)) + set(i); + else + clear(i); + if (tmp) + set(_AP_W - 1 - i); + else + clear(_AP_W - 1 - i); + } + clearUnusedBits(); + return *this; + } + + /*Return true if the value of ap_private instance is zero*/ + INLINE bool iszero () const { + return isMinValue(); + } + + /* x < 0 */ + INLINE bool sign () const { + if (isNegative()) + return true; + return false; + } + + /* x[i] = !x[i] */ + INLINE void invert (int i) { + assert( i >= 0 && "Attempting to read bit with negative index"); + assert( i < _AP_W && "Attempting to read bit beyond MSB"); + flip(i); + } + + /* x[i] */ + INLINE bool test (int i) const { + assert( i >= 0 && "Attempting to read bit with negative index"); + assert( i < _AP_W && "Attempting to read bit beyond MSB"); + return operator[](i); + } + + //Set the ith bit into v + INLINE void set (int i, bool v) { + assert( i >= 0 && "Attempting to write bit with negative index"); + assert( i < _AP_W && "Attempting to write bit beyond MSB"); + v ? set(i) : clear(i); + } + + //Set the ith bit into v + INLINE void set_bit (int i, bool v) { + assert( i >= 0 && "Attempting to write bit with negative index"); + assert( i < _AP_W && "Attempting to write bit beyond MSB"); + v ? set(i) : clear(i); + } + + INLINE ap_private& set(uint32_t bitPosition) { + pVal[whichWord(bitPosition)] |= maskBit(bitPosition); + clearUnusedBits(); + return *this; + } + + INLINE void set() { + for (uint32_t i = 0; i < _AP_N; ++i) + pVal[i] = ~0ULL; + clearUnusedBits(); + } + + //Get the value of ith bit + INLINE bool get (int i) const { + assert( i >= 0 && "Attempting to read bit with negative index"); + assert( i < _AP_W && "Attempting to read bit beyond MSB"); + return operator [](i); + } + + //Get the value of ith bit + INLINE bool get_bit (int i) const { + assert( i >= 0 && "Attempting to read bit with negative index"); + assert( i < _AP_W && "Attempting to read bit beyond MSB"); + return operator [](i); + } + + //This is used for sc_lv and sc_bv, which is implemented by sc_uint + //Rotate an ap_private object n places to the left + INLINE void lrotate(int n) { + assert( n >= 0 && "Attempting to shift negative index"); + assert( n < _AP_W && "Shift value larger than bit width"); + operator = (shl(n) | lshr(_AP_W - n)); + } + + //This is used for sc_lv and sc_bv, which is implemented by sc_uint + //Rotate an ap_private object n places to the right + INLINE void rrotate(int n) { + assert( n >= 0 && "Attempting to shift negative index"); + assert( n < _AP_W && "Shift value larger than bit width"); + operator = (lshr(n) | shl(_AP_W - n)); + } + + /// Set the given bit to 0 whose position is given as "bitPosition". + /// @brief Set a given bit to 0. + ap_private& clear(uint32_t bitPosition) { + pVal[whichWord(bitPosition)] &= ~maskBit(bitPosition); + clearUnusedBits(); + return *this; + } + + /// @brief Set every bit to 0. + void clear() { + memset(pVal, 0, _AP_N * APINT_WORD_SIZE); + } + + /// @brief Toggle every bit to its opposite value. + ap_private& flip() { + for (uint32_t i = 0; i < _AP_N; ++i) + pVal[i] ^= ~0ULL; + clearUnusedBits(); + return *this; + } + + /// Toggle a given bit to its opposite value whose position is given + /// as "bitPosition". + /// @brief Toggles a given bit to its opposite value. + ap_private& flip(uint32_t bitPosition) { + assert(bitPosition < BitWidth && "Out of the bit-width range!"); + if ((*this)[bitPosition]) clear(bitPosition); + else set(bitPosition); + return *this; + } + + //complements every bit + INLINE void b_not() { + flip(); + } + + ap_private getLoBits(uint32_t numBits) const { + return ap_private_ops::lshr(ap_private_ops::shl(*this, _AP_W - numBits), + _AP_W - numBits); + } + + ap_private getHiBits(uint32_t numBits) const { + return ap_private_ops::lshr(*this, _AP_W - numBits); + } + + //Binary Arithmetic + //----------------------------------------------------------- + + template + INLINE ap_private + operator & (const ap_concat_ref<_AP_W2, _AP_T2, _AP_W3, _AP_T3>& a2) { + return *this & a2.get(); + } + + template + INLINE ap_private + operator | (const ap_concat_ref<_AP_W2, _AP_T2, _AP_W3, _AP_T3>& a2) { + return *this | a2.get(); + } + + template + INLINE ap_private + operator ^ (const ap_concat_ref<_AP_W2, _AP_T2, _AP_W3, _AP_T3>& a2) { + return *this ^ a2.get(); + } + + + ///Arithmetic assign + //------------------------------------------------------------- + +#define OP_BIN_LOGIC_ASSIGN_AP(Sym) \ + template \ + INLINE ap_private& operator Sym(const ap_private<_AP_W1, _AP_S1, _AP_N1>& RHS) { \ + uint32_t numWords = AESL_std::min(_AP_N, _AP_N1); \ + uint32_t i; \ + for (i = 0; i < numWords; ++i) \ + pVal[i] Sym RHS.pVal[i]; \ + if (_AP_N1 < _AP_N) { \ + uint64_t ext = RHS.isNegative()?~0ULL:0; \ + for (;i<_AP_N; i++) \ + pVal[i] Sym ext; \ + } \ + clearUnusedBits(); \ + return *this; \ + } + + OP_BIN_LOGIC_ASSIGN_AP(&=); + OP_BIN_LOGIC_ASSIGN_AP(|=); + OP_BIN_LOGIC_ASSIGN_AP(^=); +#undef OP_BIN_LOGIC_ASSIGN_AP + + /// Adds the RHS APint to this ap_private. + /// @returns this, after addition of RHS. + /// @brief Addition assignment operator. + template + INLINE ap_private& operator+=(const ap_private<_AP_W1, _AP_S1, _AP_N1>& RHS) { + add(pVal, pVal, RHS.pVal, _AP_N, _AP_N, _AP_N1, _AP_S, _AP_S1); + clearUnusedBits(); + return *this; + } + + template + INLINE ap_private& operator-=(const ap_private<_AP_W1, _AP_S1, _AP_N1>& RHS) { + sub(pVal, pVal, RHS.pVal, _AP_N, _AP_N, _AP_N1, _AP_S, _AP_S1); + clearUnusedBits(); + return *this; + } + + template + ap_private& operator*=(const ap_private<_AP_W1, _AP_S1, _AP_N1>& RHS) { + // Get some bit facts about LHS and check for zero + uint32_t lhsBits = getActiveBits(); + uint32_t lhsWords = !lhsBits ? 0 : whichWord(lhsBits - 1) + 1; + if (!lhsWords) { + // 0 * X ===> 0 + return *this; + } + + ap_private dupRHS = RHS; + // Get some bit facts about RHS and check for zero + uint32_t rhsBits = dupRHS.getActiveBits(); + uint32_t rhsWords = !rhsBits ? 0 : whichWord(rhsBits - 1) + 1; + if (!rhsWords) { + // X * 0 ===> 0 + clear(); + return *this; + } + + // Allocate space for the result + uint32_t destWords = rhsWords + lhsWords; + uint64_t *dest = getMemory(destWords); + + // Perform the long multiply + mul(dest, pVal, lhsWords, dupRHS.pVal, rhsWords, destWords); + + // Copy result back into *this + clear(); + uint32_t wordsToCopy = destWords >= _AP_N ? _AP_N : destWords; + + memcpy(pVal, dest, wordsToCopy* APINT_WORD_SIZE); + + uint64_t ext = (isNegative() ^ RHS.isNegative()) ? ~0ULL : 0ULL; + for (int i=wordsToCopy; i<_AP_N; i++) + pVal[i]=ext; + clearUnusedBits(); + // delete dest array and return + free(dest); + return *this; + } + +#define OP_ASSIGN_AP(Sym) \ + template \ + INLINE ap_private& operator Sym##=(const ap_private<_AP_W2,_AP_S2>& op) \ + { \ + *this=operator Sym (op); \ + return *this; \ + } \ + + OP_ASSIGN_AP(/) + OP_ASSIGN_AP(%) +#undef OP_ASSIGN_AP + +#define OP_BIN_LOGIC_AP(Sym) \ + template \ + INLINE \ + typename RType<_AP_W1, _AP_S1>::logic \ + operator Sym (const ap_private<_AP_W1, _AP_S1, _AP_N1>& RHS) const { \ + enum { numWords = (RType<_AP_W1, _AP_S1>::logic_w +APINT_BITS_PER_WORD-1)/APINT_BITS_PER_WORD}; \ + typename RType<_AP_W1, _AP_S1>::logic Result; \ + uint64_t *val = Result.pVal; \ + uint32_t i; \ + uint32_t min_N = std::min(_AP_N, _AP_N1); \ + uint32_t max_N = std::max(_AP_N, _AP_N1); \ + for (i = 0; i < min_N; ++i) \ + val[i] = pVal[i] Sym RHS.pVal[i]; \ + if (numWords > i) { \ + const uint64_t* tmpVal = (_AP_N>_AP_N1 ? pVal : RHS.pVal)+i; \ + uint64_t ext = ((_AP_N<_AP_N1 && isNegative() )||(_AP_N1 < _AP_N && RHS.isNegative())) ? ~0ULL : 0; \ + for (;i i) { \ + uint64_t ext2 = ((_AP_N>_AP_N1 && isNegative() )||(_AP_N1 > _AP_N && RHS.isNegative())) ? ~0ULL : 0; \ + val[i] = ext Sym ext2; \ + } \ + } \ + Result.clearUnusedBits(); \ + return Result; \ + } + + OP_BIN_LOGIC_AP(|); + OP_BIN_LOGIC_AP(&); + OP_BIN_LOGIC_AP(^); + +#undef OP_BIN_LOGIC_AP + + template + INLINE typename RType<_AP_W1,_AP_S1>::plus operator+(const ap_private<_AP_W1, _AP_S1, _AP_N1>& RHS) const { + // assert(BitWidth == RHS.BitWidth && "Bit widths must be the same"); + typename RType<_AP_W1,_AP_S1>::plus Result; + bool carry = add(Result.pVal, this->pVal, RHS.pVal, (RType<_AP_W1,_AP_S1>::plus_w + 63) / 64, _AP_N, _AP_N1, _AP_S, _AP_S1); + if ((RType<_AP_W1,_AP_S1>::plus_w + 63) / 64> std::max(_AP_W, _AP_W1) ) + Result.pVal[(RType<_AP_W1,_AP_S1>::plus_w + 63)/64 - 1] = carry; + Result.clearUnusedBits(); + return Result; + } + + template + INLINE typename RType<_AP_W1,_AP_S1>::minus operator-(const ap_private<_AP_W1, _AP_S1, _AP_N1>& RHS) const { + typename RType<_AP_W1,_AP_S1>::minus Result; + bool borrow = sub(Result.pVal, this->pVal, RHS.pVal, (RType<_AP_W1,_AP_S1>::minus_w + 63) / 64, _AP_N, _AP_N1, _AP_S, _AP_S1); + if ((RType<_AP_W1,_AP_S1>::minus_w + 63) / 64 > AESL_std::max(_AP_W, _AP_W1) ) { + Result.pVal[(RType<_AP_W1,_AP_S1>::minus_w+63)/64 - 1] = borrow; + } + Result.clearUnusedBits(); + return Result; + } + + template + typename RType<_AP_W1, _AP_S1>::mult operator*(const ap_private<_AP_W1, _AP_S1, _AP_N1>& RHS) const { + + // Get some bit facts about LHS and check for zero + uint32_t lhsBits = getActiveBits(); + uint32_t lhsWords = !lhsBits ? 0 : whichWord(lhsBits - 1) + 1; + if (!lhsWords) + // 0 * X ===> 0 + return typename RType<_AP_W1, _AP_S1>::mult(); + + // Get some bit facts about RHS and check for zero + uint32_t rhsBits = RHS.getActiveBits(); + uint32_t rhsWords = !rhsBits ? 0 : whichWord(rhsBits - 1) + 1; + if (!rhsWords) { + // X * 0 ===> 0 + return typename RType<_AP_W1, _AP_S1>::mult(); + } + + //extend size to avoid result loss + typename RType<_AP_W1, _AP_S1>::mult dupLHS = *this; + typename RType<_AP_W1, _AP_S1>::mult dupRHS = RHS; + lhsBits = dupLHS.getActiveBits(); + lhsWords = !lhsBits ? 0 : whichWord(lhsBits - 1) + 1; + rhsBits = dupRHS.getActiveBits(); + rhsWords = !rhsBits ? 0 : whichWord(rhsBits - 1) + 1; + + // Allocate space for the result + enum { destWords =(RType<_AP_W1, _AP_S1>::mult_w+APINT_BITS_PER_WORD-1)/APINT_BITS_PER_WORD}; + int destw = destWords; + typename RType<_AP_W1, _AP_S1>::mult Result; + uint64_t *dest = Result.pVal; + uint64_t ext = (isNegative() ^ RHS.isNegative()) ? ~0ULL : 0; + + // Perform the long multiply + mul(dest, dupLHS.pVal, lhsWords, dupRHS.pVal, rhsWords, destWords); + + for (int i=lhsWords+rhsWords; i + INLINE typename RType<_AP_W2,_AP_S2>::div + operator / (const ap_private<_AP_W2,_AP_S2>& op) const { + ap_private lhs=ap_private(*this); + ap_private rhs=ap_private(op); + return typename RType<_AP_W2,_AP_S2>::div((_AP_S||_AP_S2)?lhs.sdiv(rhs):lhs.udiv(rhs)); + } + + template + INLINE typename RType<_AP_W2,_AP_S2>::mod + operator % (const ap_private<_AP_W2,_AP_S2>& op) const { + ap_private lhs=*this; + ap_private rhs= op; + typename RType<_AP_W2,_AP_S2>::mod res = typename RType<_AP_W2,_AP_S2>::mod(_AP_S?lhs.srem(rhs):lhs.urem(rhs)); + return res; + } + + template + INLINE ap_private + operator << (const ap_private<_AP_W2, _AP_S2>& op2) const { + uint32_t sh=op2.to_uint(); + return *this << sh; + } + + INLINE ap_private + operator << (uint32_t sh) const { + ap_private r(*this); + bool overflow=(sh>=length()); + if(overflow) + r.clear(); + else + r = ap_private(r.shl(sh)); + return r; + } + + template + INLINE ap_private + operator >> (const ap_private<_AP_W2, _AP_S2>& op2) const { + uint32_t sh = op2.to_uint(); + return *this >> sh; + } + + INLINE ap_private + operator >> (uint32_t sh) const { + ap_private r(*this); + bool overflow=(sh>=_AP_W); + bool neg_v=r.isNegative(); + if(_AP_S) { + if(overflow) + neg_v?r.set():r.clear(); + else + return r.ashr(sh); + } else { + if(overflow) + r.clear(); + else + return r.lshr(sh); + } + return r; + } + + ///Shift assign + //------------------------------------------------------------------ +#define OP_ASSIGN_AP(Sym) \ + template \ + INLINE ap_private& operator Sym##=(int op) \ + { \ + *this = operator Sym (op); \ + return *this; \ + } \ + INLINE ap_private& operator Sym##=(unsigned int op) \ + { \ + *this = operator Sym (op); \ + return *this; \ + } \ + template \ + INLINE ap_private& operator Sym##=(const ap_private<_AP_W2,_AP_S2>& op) \ + { \ + *this = operator Sym (op); \ + return *this; \ + } + OP_ASSIGN_AP(>>) + OP_ASSIGN_AP(<<) +#undef OP_ASSIGN_AP + ///Comparisons + //----------------------------------------------------------------- + bool operator==(const ap_private& RHS) const { + // Get some facts about the number of bits used in the two operands. + uint32_t n1 = getActiveBits(); + uint32_t n2 = RHS.getActiveBits(); + + // If the number of bits isn't the same, they aren't equal + if (n1 != n2) + return false; + + // If the number of bits fits in a word, we only need to compare the low word. + if (n1 <= APINT_BITS_PER_WORD) + return pVal[0] == RHS.pVal[0]; + + // Otherwise, compare everything + for (int i = whichWord(n1 - 1); i >= 0; --i) + if (pVal[i] != RHS.pVal[i]) + return false; + return true; + } + + template + INLINE bool operator == (const ap_private<_AP_W2, _AP_S2>& op) const { + enum { _AP_MAX_W = AP_MAX(_AP_W+(_AP_S||_AP_S2),_AP_W2+(_AP_S||_AP_S2))}; + ap_private<_AP_MAX_W, _AP_S|_AP_S2> lhs(*this); + ap_private<_AP_MAX_W, _AP_S|_AP_S2> rhs(op); + return lhs==rhs; + } + + bool operator==(uint64_t Val) const { + uint32_t n = getActiveBits(); + if (n <= APINT_BITS_PER_WORD) + return pVal[0] == Val; + else + return false; + } + + template + INLINE bool operator != (const ap_private<_AP_W2, _AP_S2>& op) const { + return !(*this==op); + } + + template + INLINE bool operator!=(const ap_private<_AP_W, _AP_S1, _AP_N>& RHS) const { + return !((*this) == RHS); + } + + INLINE bool operator!=(uint64_t Val) const { + return !((*this) == Val); + } + + + template + INLINE bool operator <= (const ap_private<_AP_W2,_AP_S2>& op) const { + return !(*this>op); + } + + INLINE bool operator <(const ap_private& op) const { + return _AP_S ? slt(op):ult(op); + } + + template + INLINE bool operator < (const ap_private<_AP_W2, _AP_S2>& op) const { + enum { _AP_MAX_W = AP_MAX(_AP_W+(_AP_S||_AP_S2),_AP_W2+(_AP_S||_AP_S2))}; + ap_private<_AP_MAX_W, _AP_S> lhs(*this); + ap_private<_AP_MAX_W, _AP_S2> rhs(op); + if (_AP_S == _AP_S2) + return _AP_S?lhs.slt(rhs):lhs.ult(rhs); + else + if (_AP_S) + if (_AP_W2 >= _AP_W) + return lhs.ult(rhs); + else + return lhs.slt(rhs); + else + if (_AP_W >= _AP_W2) + return lhs.ult(rhs); + else + return lhs.slt(rhs); + } + + template + INLINE bool operator >=(const ap_private<_AP_W2,_AP_S2>& op) const { + return !(*this + INLINE bool operator > (const ap_private<_AP_W2, _AP_S2>& op) const { + enum { _AP_MAX_W = AP_MAX(_AP_W+(_AP_S||_AP_S2),_AP_W2+(_AP_S||_AP_S2))}; + ap_private<_AP_MAX_W, _AP_S> lhs(*this); + ap_private<_AP_MAX_W, _AP_S2> rhs(op); + if (_AP_S == _AP_S2) + return _AP_S?lhs.sgt(rhs):lhs.ugt(rhs); + else + if (_AP_S) + if (_AP_W2 >= _AP_W) + return lhs.ugt(rhs); + else + return lhs.sgt(rhs); + else + if (_AP_W >= _AP_W2) + return lhs.ugt(rhs); + else + return lhs.sgt(rhs); + } + + ///Bit and Part Select + //-------------------------------------------------------------- + INLINE ap_range_ref<_AP_W,_AP_S> + operator () (int Hi, int Lo) { + assert((Hi < _AP_W) && (Lo < _AP_W)&&"Out of bounds in range()"); + return ap_range_ref<_AP_W,_AP_S>(this, Hi, Lo); + } + + INLINE ap_range_ref<_AP_W,_AP_S> + operator () (int Hi, int Lo) const { + assert((Hi < _AP_W) && (Lo < _AP_W)&&"Out of bounds in range()"); + return ap_range_ref<_AP_W,_AP_S>(const_cast*>(this), Hi, Lo); + } + + INLINE ap_range_ref<_AP_W,_AP_S> + range (int Hi, int Lo) const { + assert((Hi < _AP_W) && (Lo < _AP_W)&&"Out of bounds in range()"); + return ap_range_ref<_AP_W,_AP_S>((const_cast*> (this)), Hi, Lo); + } + + INLINE ap_range_ref<_AP_W,_AP_S> + range (int Hi, int Lo) { + assert((Hi < _AP_W) && (Lo < _AP_W)&&"Out of bounds in range()"); + return ap_range_ref<_AP_W,_AP_S>(this, Hi, Lo); + } + + template + INLINE ap_range_ref<_AP_W,_AP_S> + range (const ap_private<_AP_W2, _AP_S2> &HiIdx, + const ap_private<_AP_W3, _AP_S3> &LoIdx) { + int Hi = HiIdx.to_int(); + int Lo = LoIdx.to_int(); + assert((Hi < _AP_W) && (Lo < _AP_W) && "Out of bounds in range()"); + return ap_range_ref<_AP_W,_AP_S>(this, Hi, Lo); + } + + template + INLINE ap_range_ref<_AP_W,_AP_S> + operator () (const ap_private<_AP_W2, _AP_S2> &HiIdx, + const ap_private<_AP_W3, _AP_S3> &LoIdx) { + int Hi = HiIdx.to_int(); + int Lo = LoIdx.to_int(); + assert((Hi < _AP_W) && (Lo < _AP_W) && "Out of bounds in range()"); + return ap_range_ref<_AP_W,_AP_S>(this, Hi, Lo); + } + + template + INLINE ap_range_ref<_AP_W,_AP_S> + range (const ap_private<_AP_W2, _AP_S2> &HiIdx, + const ap_private<_AP_W3, _AP_S3> &LoIdx) const { + int Hi = HiIdx.to_int(); + int Lo = LoIdx.to_int(); + assert((Hi < _AP_W) && (Lo < _AP_W) && "Out of bounds in range()"); + return ap_range_ref<_AP_W,_AP_S>(const_cast(this), Hi, Lo); + } + + template + INLINE ap_range_ref<_AP_W,_AP_S> + operator () (const ap_private<_AP_W2, _AP_S2> &HiIdx, + const ap_private<_AP_W3, _AP_S3> &LoIdx) const { + int Hi = HiIdx.to_int(); + int Lo = LoIdx.to_int(); + return this->range(Hi, Lo); + } + + INLINE ap_bit_ref<_AP_W,_AP_S> operator [] (uint32_t index) { + assert(index >= 0&&"Attempting to read bit with negative index"); + assert(index < _AP_W && "Attempting to read bit beyond MSB"); + return ap_bit_ref<_AP_W,_AP_S>( *this, index ); + } + + template + INLINE ap_bit_ref<_AP_W,_AP_S> operator [] (const ap_private<_AP_W2,_AP_S2> &index) { + assert(index >= 0 && "Attempting to read bit with negative index"); + assert(index < _AP_W && "Attempting to read bit beyond MSB"); + return ap_bit_ref<_AP_W,_AP_S>( *this, index.to_int() ); + } + + template + INLINE bool operator [] (const ap_private<_AP_W2,_AP_S2>& index) const { + assert(index < _AP_W && "Attempting to read bit beyond MSB"); + ap_bit_ref<_AP_W,_AP_S> br =operator [] (index); + return br.to_bool(); + } + + INLINE bool operator [](uint32_t bitPosition) const { + return (maskBit(bitPosition) & (pVal[whichWord(bitPosition)])) != 0; + } + + INLINE ap_bit_ref<_AP_W,_AP_S> bit (int index) { + assert(index >= 0 && "Attempting to read bit with negative index"); + assert(index < _AP_W && "Attempting to read bit beyond MSB"); + return ap_bit_ref<_AP_W,_AP_S>( *this, index ); + } + + template + INLINE ap_bit_ref<_AP_W,_AP_S> bit (const ap_private<_AP_W2,_AP_S2> &index) { + assert(index >= 0 && "Attempting to read bit with negative index"); + assert(index < _AP_W &&"Attempting to read bit beyond MSB"); + return ap_bit_ref<_AP_W,_AP_S>( *this, index.to_int() ); + } + + INLINE bool bit (int index) const { + assert(index >= 0 && "Attempting to read bit with negative index"); + assert(index < _AP_W && "Attempting to read bit beyond MSB"); + ap_bit_ref<_AP_W,_AP_S> br(const_cast*>(this), index); + return br.to_bool(); + } + + template + INLINE bool bit (const ap_private<_AP_W2,_AP_S2>& index) const { + assert(index < _AP_W && "Attempting to read bit beyond MSB"); + ap_bit_ref<_AP_W,_AP_S> br = bit(index); + return br.to_bool(); + } + + template + INLINE ap_concat_ref<_AP_W,ap_private<_AP_W, _AP_S>,_AP_W2,ap_private<_AP_W2,_AP_S2> > concat(ap_private<_AP_W2,_AP_S2>& a2) { + return ap_concat_ref<_AP_W, ap_private<_AP_W, _AP_S>, _AP_W2, ap_private<_AP_W2,_AP_S2> >(*this, a2); + } + + template + INLINE ap_concat_ref<_AP_W,ap_private<_AP_W, _AP_S>,_AP_W2,ap_private<_AP_W2,_AP_S2> > concat(const ap_private<_AP_W2,_AP_S2>& a2) const { + return ap_concat_ref<_AP_W, ap_private<_AP_W, _AP_S>, _AP_W2, ap_private<_AP_W2,_AP_S2> >(const_cast& >(*this), + const_cast& >(a2)); + } + + template + INLINE ap_concat_ref<_AP_W, ap_private, _AP_W2, ap_private<_AP_W2, _AP_S2> > + operator, (ap_private<_AP_W2, _AP_S2>& a2) { + return ap_concat_ref<_AP_W, ap_private, _AP_W2, ap_private<_AP_W2, + _AP_S2> >(*this, a2); + } + + template + INLINE ap_concat_ref<_AP_W, ap_private, _AP_W2, ap_private<_AP_W2, _AP_S2> > + operator, (ap_private<_AP_W2, _AP_S2>& a2) const { + return ap_concat_ref<_AP_W, ap_private, _AP_W2, ap_private<_AP_W2, + _AP_S2> >(const_cast& >(*this), a2); + } + + template + INLINE ap_concat_ref<_AP_W, ap_private, _AP_W2, ap_private<_AP_W2, _AP_S2> > + operator, (const ap_private<_AP_W2, _AP_S2>& a2) { + return ap_concat_ref<_AP_W, ap_private, _AP_W2, ap_private<_AP_W2, + _AP_S2> >(*this, const_cast& >(a2)); + } + + template + INLINE ap_concat_ref<_AP_W, ap_private, _AP_W2, ap_private<_AP_W2, _AP_S2> > + operator, (const ap_private<_AP_W2, _AP_S2>& a2) const { + return ap_concat_ref<_AP_W, ap_private, _AP_W2, ap_private<_AP_W2, + _AP_S2> >(const_cast& >(*this), const_cast& >(a2)); + } + + template + INLINE ap_concat_ref<_AP_W, ap_private<_AP_W, _AP_S>, _AP_W2, ap_range_ref<_AP_W2, _AP_S2> > + operator, (const ap_range_ref<_AP_W2, _AP_S2> &a2) const { + return ap_concat_ref<_AP_W, ap_private<_AP_W, _AP_S>, _AP_W2, + ap_range_ref<_AP_W2, _AP_S2> >(const_cast& >(*this), + const_cast& >(a2)); + } + + template + INLINE ap_concat_ref<_AP_W, ap_private<_AP_W, _AP_S>, _AP_W2, ap_range_ref<_AP_W2, _AP_S2> > + operator, (ap_range_ref<_AP_W2, _AP_S2> &a2) { + return ap_concat_ref<_AP_W, ap_private<_AP_W, _AP_S>, _AP_W2, + ap_range_ref<_AP_W2, _AP_S2> >(*this, a2); + } + + template + INLINE ap_concat_ref<_AP_W, ap_private<_AP_W, _AP_S>, 1, ap_bit_ref<_AP_W2, _AP_S2> > + operator, (const ap_bit_ref<_AP_W2, _AP_S2> &a2) const { + return ap_concat_ref<_AP_W, ap_private<_AP_W, _AP_S>, 1, + ap_bit_ref<_AP_W2, _AP_S2> >(const_cast& >(*this), + const_cast& >(a2)); + } + + template + INLINE ap_concat_ref<_AP_W, ap_private<_AP_W, _AP_S>, 1, ap_bit_ref<_AP_W2, _AP_S2> > + operator, (ap_bit_ref<_AP_W2, _AP_S2> &a2) { + return ap_concat_ref<_AP_W, ap_private<_AP_W, _AP_S>, 1, + ap_bit_ref<_AP_W2, _AP_S2> >(*this, a2); + } + + template + INLINE + ap_concat_ref<_AP_W, ap_private<_AP_W, _AP_S>, _AP_W2+_AP_W3, ap_concat_ref<_AP_W2, _AP_T2, _AP_W3, _AP_T3> > + operator, (const ap_concat_ref<_AP_W2, _AP_T2, _AP_W3, _AP_T3> &a2) const { + return ap_concat_ref<_AP_W, ap_private<_AP_W, _AP_S>, _AP_W2+_AP_W3, + ap_concat_ref<_AP_W2, _AP_T2, _AP_W3, _AP_T3> >(const_cast& >(*this), + const_cast& >(a2)); + } + + template + INLINE + ap_concat_ref<_AP_W, ap_private<_AP_W, _AP_S>, _AP_W2+_AP_W3, ap_concat_ref<_AP_W2, _AP_T2, _AP_W3, _AP_T3> > + operator, (ap_concat_ref<_AP_W2, _AP_T2, _AP_W3, _AP_T3> &a2) { + return ap_concat_ref<_AP_W, ap_private<_AP_W, _AP_S>, _AP_W2+_AP_W3, + ap_concat_ref<_AP_W2, _AP_T2, _AP_W3, _AP_T3> >(*this, a2); + } + + template + INLINE ap_concat_ref<_AP_W, ap_private, _AP_W2, af_range_ref<_AP_W2, _AP_I2, _AP_S2, _AP_Q2, _AP_O2, _AP_N2> > + operator, (const af_range_ref<_AP_W2, _AP_I2, _AP_S2, _AP_Q2, + _AP_O2, _AP_N2> &a2) const { + return ap_concat_ref<_AP_W, ap_private, _AP_W2, af_range_ref<_AP_W2, + _AP_I2, _AP_S2, _AP_Q2, _AP_O2, _AP_N2> >(const_cast& >(*this), + const_cast& >(a2)); + } + + template + INLINE ap_concat_ref<_AP_W, ap_private, _AP_W2, af_range_ref<_AP_W2, _AP_I2, _AP_S2, _AP_Q2, _AP_O2, _AP_N2> > + operator, (af_range_ref<_AP_W2, _AP_I2, _AP_S2, _AP_Q2, + _AP_O2, _AP_N2> &a2) { + return ap_concat_ref<_AP_W, ap_private, _AP_W2, af_range_ref<_AP_W2, + _AP_I2, _AP_S2, _AP_Q2, _AP_O2, _AP_N2> >(*this, a2); + } + + template + INLINE ap_concat_ref<_AP_W, ap_private, 1, af_bit_ref<_AP_W2, _AP_I2, _AP_S2, _AP_Q2, _AP_O2, _AP_N2> > + operator, (const af_bit_ref<_AP_W2, _AP_I2, _AP_S2, _AP_Q2, + _AP_O2, _AP_N2> &a2) const { + return ap_concat_ref<_AP_W, ap_private, 1, af_bit_ref<_AP_W2, + _AP_I2, _AP_S2, _AP_Q2, _AP_O2, _AP_N2> >(const_cast& >(*this), + const_cast& >(a2)); + } + + template + INLINE ap_concat_ref<_AP_W, ap_private, 1, af_bit_ref<_AP_W2, _AP_I2, _AP_S2, _AP_Q2, _AP_O2, _AP_N2> > + operator, (af_bit_ref<_AP_W2, _AP_I2, _AP_S2, _AP_Q2, + _AP_O2, _AP_N2> &a2) { + return ap_concat_ref<_AP_W, ap_private, 1, af_bit_ref<_AP_W2, + _AP_I2, _AP_S2, _AP_Q2, _AP_O2, _AP_N2> >(*this, a2); + } + + INLINE ap_private<_AP_W,false> get() const { + ap_private<_AP_W,false> ret(*this); + return ret; + } + + template + INLINE void set(const ap_private<_AP_W3, false> & val) { + operator = (ap_private<_AP_W3, _AP_S>(val)); + } + + /// @} + /// @name Value Tests + /// @{ + /// This tests the high bit of this ap_private to determine if it is set. + /// @returns true if this ap_private is negative, false otherwise + /// @brief Determine sign of this ap_private. + INLINE bool isNegative() const { + //just for get rid of warnings + enum {shift = (_AP_W-APINT_BITS_PER_WORD*(_AP_N-1)-1)}; + static const uint64_t mask = 1ULL << (shift); + return _AP_S && (pVal[_AP_N-1]&mask); + } + + /// This tests the high bit of the ap_private to determine if it is unset. + /// @brief Determine if this ap_private Value is positive (not negative). + INLINE bool isPositive() const { + return !isNegative(); + } + + /// This tests if the value of this ap_private is strictly positive (> 0). + /// @returns true if this ap_private is Positive and not zero. + /// @brief Determine if this ap_private Value is strictly positive. + INLINE bool isStrictlyPositive() const { + return isPositive() && (*this) != 0; + } + + /// This checks to see if the value has all bits of the ap_private are set or not. + /// @brief Determine if all bits are set + INLINE bool isAllOnesValue() const { + return countPopulation() == _AP_W; + } + + /// This checks to see if the value of this ap_private is the maximum unsigned + /// value for the ap_private's bit width. + /// @brief Determine if this is the largest unsigned value. + INLINE bool isMaxValue() const { + return countPopulation() == _AP_W; + } + + /// This checks to see if the value of this ap_private is the maximum signed + /// value for the ap_private's bit width. + /// @brief Determine if this is the largest signed value. + INLINE bool isMaxSignedValue() const { + return BitWidth == 1 ? VAL == 0 : + !isNegative() && countPopulation() == _AP_W - 1; + } + + /// This checks to see if the value of this ap_private is the minimum unsigned + /// value for the ap_private's bit width. + /// @brief Determine if this is the smallest unsigned value. + INLINE bool isMinValue() const { + return countPopulation() == 0; + } + + /// This checks to see if the value of this ap_private is the minimum signed + /// value for the ap_private's bit width. + /// @brief Determine if this is the smallest signed value. + INLINE bool isMinSignedValue() const { + return BitWidth == 1 ? VAL == 1 : + isNegative() && countPopulation() == 1; + } + + /// This function returns a pointer to the internal storage of the ap_private. + /// This is useful for writing out the ap_private in binary form without any + /// conversions. + INLINE const uint64_t* getRawData() const { + if (isSingleWord()) + return &VAL; + return &pVal[0]; + } + + ap_private sqrt() const; + + /// @} + /// @Assignment Operators + /// @{ + /// @returns *this after assignment of RHS. + /// @brief Copy assignment operator. + INLINE ap_private& operator=(const ap_private& RHS) { + if (this != &RHS) + memcpy(pVal, RHS.pVal, _AP_N * APINT_WORD_SIZE); + return *this; + } + INLINE ap_private& operator=(const volatile ap_private& RHS) { + if (this != &RHS) + for (int i=0; i<_AP_N; ++i) + pVal[i] = RHS.pVal[i]; + return *this; + } + INLINE volatile ap_private& operator=(const ap_private& RHS) volatile { + if (this != &RHS) + for (int i=0; i<_AP_N; ++i) + pVal[i] = RHS.pVal[i]; + return *this; + } + INLINE volatile ap_private& operator=(const volatile ap_private& RHS) volatile { + if (this != &RHS) + for (int i=0; i<_AP_N; ++i) + pVal[i] = RHS.pVal[i]; + return *this; + } + + template + INLINE ap_private& operator=(const ap_private<_AP_W1, _AP_S1, _AP_N1>& RHS) { + if (_AP_S1) + cpSextOrTrunc(RHS); + else + cpZextOrTrunc(RHS); + clearUnusedBits(); + return *this; + } + + template + INLINE ap_private& operator=(const volatile ap_private<_AP_W1, _AP_S1, _AP_N1>& RHS) { + if (_AP_S1) + cpSextOrTrunc(RHS); + else + cpZextOrTrunc(RHS); + clearUnusedBits(); + return *this; + } + + template + INLINE ap_private& operator=(const ap_private<_AP_W1, _AP_S1, 1>& RHS) { + static const uint64_t that_sign_ext_mask = (_AP_W1==APINT_BITS_PER_WORD)?0:~0ULL>>(_AP_W1%APINT_BITS_PER_WORD)<<(_AP_W1%APINT_BITS_PER_WORD); + if (RHS.isNegative()) { + pVal[0] = RHS.VAL | that_sign_ext_mask; + memset(pVal+1,~0, APINT_WORD_SIZE*(_AP_N-1)); + } else { + pVal[0] = RHS.VAL; + memset(pVal+1, 0, APINT_WORD_SIZE*(_AP_N-1)); + } + clearUnusedBits(); + return *this; + } + + template + INLINE ap_private& operator=(const volatile ap_private<_AP_W1, _AP_S1, 1>& RHS) { + static const uint64_t that_sign_ext_mask = (_AP_W1==APINT_BITS_PER_WORD)?0:~0ULL>>(_AP_W1%APINT_BITS_PER_WORD)<<(_AP_W1%APINT_BITS_PER_WORD); + if (RHS.isNegative()) { + pVal[0] = RHS.VAL | that_sign_ext_mask; + memset(pVal+1,~0, APINT_WORD_SIZE*(_AP_N-1)); + } else { + pVal[0] = RHS.VAL; + memset(pVal+1, 0, APINT_WORD_SIZE*(_AP_N-1)); + } + clearUnusedBits(); + return *this; + } + + /// @} + /// @name Unary Operators + /// @{ + /// @returns a new ap_private value representing *this incremented by one + /// @brief Postfix increment operator. + INLINE const ap_private operator++(int) { + ap_private API(*this); + ++(*this); + return API; + } + + /// @returns *this incremented by one + /// @brief Prefix increment operator. + INLINE ap_private& operator++() { + add_1(pVal, pVal, _AP_N, 1); + clearUnusedBits(); + return *this; + } + + /// @returns a new ap_private representing *this decremented by one. + /// @brief Postfix decrement operator. + INLINE const ap_private operator--(int) { + ap_private API(*this); + --(*this); + return API; + } + + /// @returns *this decremented by one. + /// @brief Prefix decrement operator. + INLINE ap_private& operator--() { + sub_1(pVal, _AP_N, 1); + clearUnusedBits(); + return *this; + } + + /// Performs a bitwise complement operation on this ap_private. + /// @returns an ap_private that is the bitwise complement of *this + /// @brief Unary bitwise complement operator. + INLINE ap_private operator~() const { + ap_private Result(*this); + Result.flip(); + return Result; + } + + /// Negates *this using two's complement logic. + /// @returns An ap_private value representing the negation of *this. + /// @brief Unary negation operator + INLINE typename RType<1,false>::minus operator-() const { + return ap_private<1,false>(0) - (*this); + } + + /// Performs logical negation operation on this ap_private. + /// @returns true if *this is zero, false otherwise. + /// @brief Logical negation operator. + INLINE bool operator !() const { + for (uint32_t i = 0; i < _AP_N; ++i) + if (pVal[i]) + return false; + return true; + } + + template + INLINE ap_private<_AP_W, _AP_S||_AP_S1, _AP_N> And(const ap_private<_AP_W, _AP_S1, _AP_N>& RHS) const { + return this->operator&(RHS); + } + template + INLINE ap_private Or(const ap_private<_AP_W, _AP_S1, _AP_N>& RHS) const { + return this->operator|(RHS); + } + template + ap_private Xor(const ap_private<_AP_W, _AP_S1, _AP_N>& RHS) const { + return this->operator^(RHS); + } + + ap_private Mul(const ap_private& RHS) const { + ap_private Result(*this); + Result *= RHS; + return Result; + } + + ap_private Add(const ap_private& RHS) const { + ap_private Result(0); + bool carry = add(Result.pVal, this->pVal, RHS.pVal, _AP_N, _AP_N, _AP_N, _AP_S, _AP_S); + Result.clearUnusedBits(); + return Result; + } + + ap_private Sub(const ap_private& RHS) const { + ap_private Result(0); + sub(Result.pVal, this->pVal, RHS.pVal, _AP_N, _AP_N, _AP_N, _AP_S, _AP_S); + Result.clearUnusedBits(); + return Result; + } + + /// Arithmetic right-shift this ap_private by shiftAmt. + /// @brief Arithmetic right-shift function. + ap_private ashr(uint32_t shiftAmt) const { + assert(shiftAmt <= BitWidth && "Invalid shift amount, too big"); + // Handle a degenerate case + if (shiftAmt == 0) + return *this; + + // Handle single word shifts with built-in ashr + if (isSingleWord()) { + if (shiftAmt == BitWidth) + return ap_private(/*BitWidth, 0*/); // undefined + else { + uint32_t SignBit = APINT_BITS_PER_WORD - BitWidth; + return ap_private(/*BitWidth,*/ + (((int64_t(VAL) << (SignBit)) >> (SignBit)) >> (shiftAmt))); + } + } + + // If all the bits were shifted out, the result is, technically, undefined. + // We return -1 if it was negative, 0 otherwise. We check this early to avoid + // issues in the algorithm below. + if (shiftAmt == BitWidth) { + if (isNegative()) + return ap_private(-1); + else + return ap_private(0); + } + + // Create some space for the result. + ap_private Retval(0); + uint64_t * val = Retval.pVal; + + // Compute some values needed by the following shift algorithms + uint32_t wordShift = shiftAmt % APINT_BITS_PER_WORD; // bits to shift per word + uint32_t offset = shiftAmt / APINT_BITS_PER_WORD; // word offset for shift + uint32_t breakWord = _AP_N - 1 - offset; // last word affected + uint32_t bitsInWord = whichBit(BitWidth); // how many bits in last word? + if (bitsInWord == 0) + bitsInWord = APINT_BITS_PER_WORD; + + // If we are shifting whole words, just move whole words + if (wordShift == 0) { + // Move the words containing significant bits + for (uint32_t i = 0; i <= breakWord; ++i) + val[i] = pVal[i+offset]; // move whole word + + // Adjust the top significant word for sign bit fill, if negative + if (isNegative()) + if (bitsInWord < APINT_BITS_PER_WORD) + val[breakWord] |= ~0ULL << (bitsInWord); // set high bits + } else { + // Shift the low order words + for (uint32_t i = 0; i < breakWord; ++i) { + // This combines the shifted corresponding word with the low bits from + // the next word (shifted into this word's high bits). + val[i] = ((pVal[i+offset]) >> (wordShift)); + val[i] |= ((pVal[i+offset+1]) << (APINT_BITS_PER_WORD - wordShift)); + } + + // Shift the break word. In this case there are no bits from the next word + // to include in this word. + val[breakWord] = (pVal[breakWord+offset]) >> (wordShift); + + // Deal with sign extenstion in the break word, and possibly the word before + // it. + if (isNegative()) { + if (wordShift > bitsInWord) { + if (breakWord > 0) + val[breakWord-1] |= + ~0ULL << (APINT_BITS_PER_WORD - (wordShift - bitsInWord)); + val[breakWord] |= ~0ULL; + } else + val[breakWord] |= (~0ULL << (bitsInWord - wordShift)); + } + } + + // Remaining words are 0 or -1, just assign them. + uint64_t fillValue = (isNegative() ? ~0ULL : 0); + for (uint32_t i = breakWord+1; i < _AP_N; ++i) + val[i] = fillValue; + Retval.clearUnusedBits(); + return Retval; + } + + /// Logical right-shift this ap_private by shiftAmt. + /// @brief Logical right-shift function. + ap_private lshr(uint32_t shiftAmt) const { + if (isSingleWord()) { + if (shiftAmt == BitWidth) + return ap_private(0); + else + return ap_private((this->VAL) >> (shiftAmt)); + } + + // If all the bits were shifted out, the result is 0. This avoids issues + // with shifting by the size of the integer type, which produces undefined + // results. We define these "undefined results" to always be 0. + if (shiftAmt == BitWidth) + return ap_private(0); + + // If none of the bits are shifted out, the result is *this. This avoids + // issues with shifting byt he size of the integer type, which produces + // undefined results in the code below. This is also an optimization. + if (shiftAmt == 0) + return *this; + + // Create some space for the result. + ap_private Retval(0); + uint64_t * val = Retval.pVal; + + // If we are shifting less than a word, compute the shift with a simple carry + if (shiftAmt < APINT_BITS_PER_WORD) { + uint64_t carry = 0; + for (int i = _AP_N-1; i >= 0; --i) { + val[i] = ((pVal[i]) >> (shiftAmt)) | carry; + carry = (pVal[i]) << (APINT_BITS_PER_WORD - shiftAmt); + } + Retval.clearUnusedBits(); + return Retval; + } + + // Compute some values needed by the remaining shift algorithms + uint32_t wordShift = shiftAmt % APINT_BITS_PER_WORD; + uint32_t offset = shiftAmt / APINT_BITS_PER_WORD; + + // If we are shifting whole words, just move whole words + if (wordShift == 0) { + for (uint32_t i = 0; i < _AP_N - offset; ++i) + val[i] = pVal[i+offset]; + for (uint32_t i = _AP_N-offset; i < _AP_N; i++) + val[i] = 0; + Retval.clearUnusedBits(); + return Retval; + } + + // Shift the low order words + uint32_t breakWord = _AP_N - offset -1; + for (uint32_t i = 0; i < breakWord; ++i) + val[i] = ((pVal[i+offset]) >> (wordShift)) | + ((pVal[i+offset+1]) << (APINT_BITS_PER_WORD - wordShift)); + // Shift the break word. + val[breakWord] = (pVal[breakWord+offset]) >> (wordShift); + + // Remaining words are 0 + for (uint32_t i = breakWord+1; i < _AP_N; ++i) + val[i] = 0; + Retval.clearUnusedBits(); + return Retval; + } + + /// Left-shift this ap_private by shiftAmt. + /// @brief Left-shift function. + ap_private shl(uint32_t shiftAmt) const { + assert(shiftAmt <= BitWidth && "Invalid shift amount, too big"); + if (isSingleWord()) { + if (shiftAmt == BitWidth) + return ap_private(0); // avoid undefined shift results + return ap_private((VAL) << (shiftAmt)); + } + + // If all the bits were shifted out, the result is 0. This avoids issues + // with shifting by the size of the integer type, which produces undefined + // results. We define these "undefined results" to always be 0. + if (shiftAmt == BitWidth) + return ap_private(0); + + // If none of the bits are shifted out, the result is *this. This avoids a + // lshr by the words size in the loop below which can produce incorrect + // results. It also avoids the expensive computation below for a common case. + if (shiftAmt == 0) + return *this; + + // Create some space for the result. + ap_private Retval(0); + uint64_t* val = Retval.pVal; + // If we are shifting less than a word, do it the easy way + if (shiftAmt < APINT_BITS_PER_WORD) { + uint64_t carry = 0; + for (uint32_t i = 0; i < _AP_N; i++) { + val[i] = ((pVal[i]) << (shiftAmt)) | carry; + carry = (pVal[i]) >> (APINT_BITS_PER_WORD - shiftAmt); + } + Retval.clearUnusedBits(); + return Retval; + } + + // Compute some values needed by the remaining shift algorithms + uint32_t wordShift = shiftAmt % APINT_BITS_PER_WORD; + uint32_t offset = shiftAmt / APINT_BITS_PER_WORD; + + // If we are shifting whole words, just move whole words + if (wordShift == 0) { + for (uint32_t i = 0; i < offset; i++) + val[i] = 0; + for (uint32_t i = offset; i < _AP_N; i++) + val[i] = pVal[i-offset]; + Retval.clearUnusedBits(); + return Retval; + } + + // Copy whole words from this to Result. + uint32_t i = _AP_N - 1; + for (; i > offset; --i) + val[i] = (pVal[i-offset]) << (wordShift) | + (pVal[i-offset-1]) >> (APINT_BITS_PER_WORD - wordShift); + val[offset] = (pVal[0]) << (wordShift); + for (i = 0; i < offset; ++i) + val[i] = 0; + Retval.clearUnusedBits(); + return Retval; + } + + INLINE ap_private rotl(uint32_t rotateAmt) const { + if (rotateAmt == 0) + return *this; + // Don't get too fancy, just use existing shift/or facilities + ap_private hi(*this); + ap_private lo(*this); + hi.shl(rotateAmt); + lo.lshr(BitWidth - rotateAmt); + return hi | lo; + } + + INLINE ap_private rotr(uint32_t rotateAmt) const { + if (rotateAmt == 0) + return *this; + // Don't get too fancy, just use existing shift/or facilities + ap_private hi(*this); + ap_private lo(*this); + lo.lshr(rotateAmt); + hi.shl(BitWidth - rotateAmt); + return hi | lo; + } + + /// Perform an unsigned divide operation on this ap_private by RHS. Both this and + /// RHS are treated as unsigned quantities for purposes of this division. + /// @returns a new ap_private value containing the division result + /// @brief Unsigned division operation. + ap_private udiv(const ap_private& RHS) const { + assert(BitWidth == RHS.BitWidth && "Bit widths must be the same"); + + // First, deal with the easy case + if (isSingleWord()) { + assert(RHS.VAL != 0 && "Divide by zero?"); + return ap_private(VAL / RHS.VAL); + } + + // Get some facts about the LHS and RHS number of bits and words + uint32_t rhsBits = RHS.getActiveBits(); + uint32_t rhsWords = !rhsBits ? 0 : (whichWord(rhsBits - 1) + 1); + assert(rhsWords && "Divided by zero???"); + uint32_t lhsBits = this->getActiveBits(); + uint32_t lhsWords = !lhsBits ? 0 : (whichWord(lhsBits - 1) + 1); + + // Deal with some degenerate cases + if (!lhsWords) + // 0 / X ===> 0 + return ap_private(0); + else if (lhsWords < rhsWords || this->ult(RHS)) { + // X / Y ===> 0, iff X < Y + return ap_private(0); + } else if (*this == RHS) { + // X / X ===> 1 + return ap_private(1); + } else if (lhsWords == 1 && rhsWords == 1) { + // All high words are zero, just use native divide + return ap_private(this->pVal[0] / RHS.pVal[0]); + } + + // We have to compute it the hard way. Invoke the Knuth divide algorithm. + ap_private Quotient(0); // to hold result. + divide(*this, lhsWords, RHS, rhsWords, &Quotient, (ap_private*)0); + return Quotient; + } + + /// Signed divide this ap_private by ap_private RHS. + /// @brief Signed division function for ap_private. + INLINE ap_private sdiv(const ap_private& RHS) const { + if (isNegative()) + if (RHS.isNegative()) + return (-(*this)).udiv(-RHS); + else + return -((-(*this)).udiv(RHS)); + else if (RHS.isNegative()) + return -(this->udiv(-RHS)); + return this->udiv(RHS); + } + + /// Perform an unsigned remainder operation on this ap_private with RHS being the + /// divisor. Both this and RHS are treated as unsigned quantities for purposes + /// of this operation. Note that this is a true remainder operation and not + /// a modulo operation because the sign follows the sign of the dividend + /// which is *this. + /// @returns a new ap_private value containing the remainder result + /// @brief Unsigned remainder operation. + ap_private urem(const ap_private& RHS) const { + if (isSingleWord()) { + assert(RHS.VAL != 0 && "Remainder by zero?"); + return ap_private(VAL % RHS.VAL); + } + + // Get some facts about the LHS + uint32_t lhsBits = getActiveBits(); + uint32_t lhsWords = !lhsBits ? 0 : (whichWord(lhsBits - 1) + 1); + + // Get some facts about the RHS + uint32_t rhsBits = RHS.getActiveBits(); + uint32_t rhsWords = !rhsBits ? 0 : (whichWord(rhsBits - 1) + 1); + assert(rhsWords && "Performing remainder operation by zero ???"); + + // Check the degenerate cases + if (lhsWords == 0) { + // 0 % Y ===> 0 + return ap_private(0); + } else if (lhsWords < rhsWords || this->ult(RHS)) { + // X % Y ===> X, iff X < Y + return *this; + } else if (*this == RHS) { + // X % X == 0; + return ap_private(0); + } else if (lhsWords == 1) { + // All high words are zero, just use native remainder + return ap_private(pVal[0] % RHS.pVal[0]); + } + + // We have to compute it the hard way. Invoke the Knuth divide algorithm. + ap_private Remainder(0); + divide(*this, lhsWords, RHS, rhsWords, (ap_private*)(0), &Remainder); + return Remainder; + } + + ap_private urem(uint64_t RHS) const { + // Get some facts about the LHS + uint32_t lhsBits = getActiveBits(); + uint32_t lhsWords = !lhsBits ? 0 : (whichWord(lhsBits - 1) + 1); + // Get some facts about the RHS + uint32_t rhsBits = 64 - CountLeadingZeros_64(RHS); // RHS.getActiveBits(); + uint32_t rhsWords = 1;//!rhsBits ? 0 : (ap_private<_AP_W, _AP_S, _AP_N>::whichWord(rhsBits - 1) + 1); + assert(rhsWords && "Performing remainder operation by zero ???"); + // Check the degenerate cases + if (lhsWords == 0) { + // 0 % Y ===> 0 + return ap_private(0); + } else if (lhsWords < rhsWords || this->ult(RHS)) { + // X % Y ===> X, iff X < Y + return *this; + } else if (*this == RHS) { + // X % X == 0; + return ap_private(0); + } else if (lhsWords == 1) { + // All high words are zero, just use native remainder + return ap_private(pVal[0] % RHS); + } + + // We have to compute it the hard way. Invoke the Knuth divide algorithm. + ap_private Remainder(0); + divide(*this, lhsWords, RHS, (ap_private*)(0), &Remainder); + return Remainder; + } + + /// Signed remainder operation on ap_private. + /// @brief Function for signed remainder operation. + INLINE ap_private srem(const ap_private& RHS) const { + if (isNegative()) { + ap_private lhs = -(*this); + if (RHS.isNegative()) { + ap_private rhs = -RHS; + return -(lhs.urem(rhs)); + } else + return -(lhs.urem(RHS)); + } else if (RHS.isNegative()) { + ap_private rhs = -RHS; + return this->urem(rhs); + } + return this->urem(RHS); + } + + /// Signed remainder operation on ap_private. + /// @brief Function for signed remainder operation. + INLINE ap_private srem(int64_t RHS) const { + if (isNegative()) + if (RHS<0) + return -((-(*this)).urem(-RHS)); + else + return -((-(*this)).urem(RHS)); + else if (RHS<0) + return this->urem(-RHS); + return this->urem(RHS); + } + + /// Sometimes it is convenient to divide two ap_private values and obtain both + /// the quotient and remainder. This function does both operations in the + /// same computation making it a little more efficient. + /// @brief Dual division/remainder interface. + static void udivrem(const ap_private& LHS, const ap_private& RHS, ap_private &Quotient, ap_private& Remainder) { + // Get some size facts about the dividend and divisor + uint32_t lhsBits = LHS.getActiveBits(); + uint32_t lhsWords = !lhsBits ? 0 : (ap_private::whichWord(lhsBits - 1) + 1); + uint32_t rhsBits = RHS.getActiveBits(); + uint32_t rhsWords = !rhsBits ? 0 : (ap_private::whichWord(rhsBits - 1) + 1); + + // Check the degenerate cases + if (lhsWords == 0) { + Quotient = 0; // 0 / Y ===> 0 + Remainder = 0; // 0 % Y ===> 0 + return; + } + + if (lhsWords < rhsWords || LHS.ult(RHS)) { + Quotient = 0; // X / Y ===> 0, iff X < Y + Remainder = LHS; // X % Y ===> X, iff X < Y + return; + } + + if (LHS == RHS) { + Quotient = 1; // X / X ===> 1 + Remainder = 0; // X % X ===> 0; + return; + } + + if (lhsWords == 1 && rhsWords == 1) { + // There is only one word to consider so use the native versions. + if (LHS.isSingleWord()) { + Quotient = ap_private(LHS.VAL / RHS.VAL); + Remainder = ap_private(LHS.VAL % RHS.VAL); + } else { + Quotient = ap_private(LHS.pVal[0] / RHS.pVal[0]); + Remainder = ap_private(LHS.pVal[0] % RHS.pVal[0]); + } + return; + } + + // Okay, lets do it the long way + divide(LHS, lhsWords, RHS, rhsWords, &Quotient, &Remainder); + } + + static void sdivrem(const ap_private &LHS, const ap_private &RHS, + ap_private &Quotient, ap_private &Remainder) { + if (LHS.isNegative()) { + if (RHS.isNegative()) + ap_private::udivrem(-LHS, -RHS, Quotient, Remainder); + else + ap_private::udivrem(-LHS, RHS, Quotient, Remainder); + Quotient = -Quotient; + Remainder = -Remainder; + } else if (RHS.isNegative()) { + ap_private::udivrem(LHS, -RHS, Quotient, Remainder); + Quotient = -Quotient; + } else { + ap_private::udivrem(LHS, RHS, Quotient, Remainder); + } + } + + /// Compares this ap_private with RHS for the validity of the equality + /// relationship. + /// @returns true if *this == Val + /// @brief Equality comparison. + template + INLINE bool eq(const ap_private<_AP_W, _AP_S1, _AP_N>& RHS) const { + return (*this) == RHS; + } + + /// Compares this ap_private with RHS for the validity of the inequality + /// relationship. + /// @returns true if *this != Val + /// @brief Inequality comparison + template + INLINE bool ne(const ap_private<_AP_W, _AP_S1, _AP_N> &RHS) const { + return !((*this) == RHS); + } + + /// Regards both *this and RHS as unsigned quantities and compares them for + /// the validity of the less-than relationship. + /// @returns true if *this < RHS when both are considered unsigned. + /// @brief Unsigned less than comparison + template + INLINE bool ult(const ap_private<_AP_W, _AP_S1, _AP_N>& RHS) const { + // Get active bit length of both operands + uint32_t n1 = getActiveBits(); + uint32_t n2 = RHS.getActiveBits(); + + // If magnitude of LHS is less than RHS, return true. + if (n1 < n2) + return true; + + // If magnitude of RHS is greather than LHS, return false. + if (n2 < n1) + return false; + + // If they bot fit in a word, just compare the low order word + if (n1 <= APINT_BITS_PER_WORD && n2 <= APINT_BITS_PER_WORD) + return pVal[0] < RHS.pVal[0]; + + // Otherwise, compare all words + uint32_t topWord = whichWord(AESL_std::max(n1,n2)-1); + for (int i = topWord; i >= 0; --i) { + if (pVal[i] > RHS.pVal[i]) + return false; + if (pVal[i] < RHS.pVal[i]) + return true; + } + return false; + } + + INLINE bool ult(uint64_t RHS) const { + // Get active bit length of both operands + uint32_t n1 = getActiveBits(); + uint32_t n2 = 64 - CountLeadingZeros_64(RHS); //RHS.getActiveBits(); + + // If magnitude of LHS is less than RHS, return true. + if (n1 < n2) + return true; + + // If magnitude of RHS is greather than LHS, return false. + if (n2 < n1) + return false; + + // If they bot fit in a word, just compare the low order word + if (n1 <= APINT_BITS_PER_WORD && n2 <= APINT_BITS_PER_WORD) + return pVal[0] < RHS; + assert(0); + } + + template + INLINE bool slt(const ap_private<_AP_W, _AP_S1, _AP_N>& RHS) const { + ap_private lhs(*this); + ap_private<_AP_W, _AP_S1, _AP_N> rhs(RHS); + bool lhsNeg = isNegative(); + bool rhsNeg = rhs.isNegative(); + if (lhsNeg) { + // Sign bit is set so perform two's complement to make it positive + lhs.flip(); + lhs++; + } + if (rhsNeg) { + // Sign bit is set so perform two's complement to make it positive + rhs.flip(); + rhs++; + } + + // Now we have unsigned values to compare so do the comparison if necessary + // based on the negativeness of the values. + if (lhsNeg) + if (rhsNeg) + return lhs.ugt(rhs); + else + return true; + else if (rhsNeg) + return false; + else + return lhs.ult(rhs); + } + + /// Regards both *this and RHS as unsigned quantities and compares them for + /// validity of the less-or-equal relationship. + /// @returns true if *this <= RHS when both are considered unsigned. + /// @brief Unsigned less or equal comparison + template + INLINE bool ule(const ap_private<_AP_W, _AP_S1, _AP_N>& RHS) const { + return ult(RHS) || eq(RHS); + } + + /// Regards both *this and RHS as signed quantities and compares them for + /// validity of the less-or-equal relationship. + /// @returns true if *this <= RHS when both are considered signed. + /// @brief Signed less or equal comparison + template + INLINE bool sle(const ap_private<_AP_W, _AP_S1, _AP_N>& RHS) const { + return slt(RHS) || eq(RHS); + } + + /// Regards both *this and RHS as unsigned quantities and compares them for + /// the validity of the greater-than relationship. + /// @returns true if *this > RHS when both are considered unsigned. + /// @brief Unsigned greather than comparison + template + INLINE bool ugt(const ap_private<_AP_W, _AP_S1, _AP_N>& RHS) const { + return !ult(RHS) && !eq(RHS); + } + + /// Regards both *this and RHS as signed quantities and compares them for + /// the validity of the greater-than relationship. + /// @returns true if *this > RHS when both are considered signed. + /// @brief Signed greather than comparison + template + INLINE bool sgt(const ap_private<_AP_W, _AP_S1, _AP_N>& RHS) const { + return !slt(RHS) && !eq(RHS); + } + + /// Regards both *this and RHS as unsigned quantities and compares them for + /// validity of the greater-or-equal relationship. + /// @returns true if *this >= RHS when both are considered unsigned. + /// @brief Unsigned greater or equal comparison + template + INLINE bool uge(const ap_private<_AP_W, _AP_S, _AP_N>& RHS) const { + return !ult(RHS); + } + + /// Regards both *this and RHS as signed quantities and compares them for + /// validity of the greater-or-equal relationship. + /// @returns true if *this >= RHS when both are considered signed. + /// @brief Signed greather or equal comparison + template + INLINE bool sge(const ap_private<_AP_W, _AP_S1, _AP_N>& RHS) const { + return !slt(RHS); + } + + template + void cpTrunc(const ap_private<_AP_W1, _AP_S1, _AP_N1>& that) { + assert(_AP_W1 > BitWidth && "Invalid ap_private Truncate request"); + assert(_AP_W1 >= MIN_INT_BITS && "Can't truncate to 0 bits"); + memcpy(pVal, that.pVal, _AP_N*APINT_WORD_SIZE); + } + + // Sign extend to a new width. + template + void cpSext(const ap_private<_AP_W1, _AP_S1, _AP_N1>& that) { + assert(_AP_W1 < BitWidth && "Invalid ap_private SignExtend request"); + assert(_AP_W1 <= MAX_INT_BITS && "Too many bits"); + // If the sign bit isn't set, this is the same as zext. + if (!that.isNegative()) { + cpZext(that); + return; + } + + // The sign bit is set. First, get some facts + enum { wordBits = _AP_W1 % APINT_BITS_PER_WORD}; + + // Mask the high order word appropriately + if (_AP_N1 == _AP_N) { + enum { newWordBits = _AP_W % APINT_BITS_PER_WORD}; + // The extension is contained to the wordsBefore-1th word. + static const uint64_t mask = wordBits?(~0ULL<<(wordBits)):0ULL; + if (_AP_N1 == 1) { + assert(0); + } else { + for (uint32_t i = 0; i < _AP_N1; ++i) + pVal[i] = that.pVal[i]; + pVal[_AP_N1-1] |= mask; + return; + } + } + + if (_AP_N1 == 1) { + assert(0);// newVal[0] = VAL | mask; + } else { + enum { newWordBits = _AP_W % APINT_BITS_PER_WORD}; + // The extension is contained to the wordsBefore-1th word. + static const uint64_t mask = wordBits?(~0ULL<<(wordBits)):0ULL; + for (uint32_t i = 0; i < _AP_N1; ++i) + pVal[i] = that.pVal[i]; + pVal[_AP_N1-1] |= mask; + } + for (uint32_t i=_AP_N1; i < _AP_N-1; i++) + pVal[i] = ~0ULL; + pVal[_AP_N-1] = ~0ULL; + clearUnusedBits(); + return; + } + + // Zero extend to a new width. + template + void cpZext(const ap_private<_AP_W1, _AP_S1, _AP_N1>& that) { + assert(_AP_W1 < BitWidth && "Invalid ap_private ZeroExtend request"); + assert(_AP_W1 <= MAX_INT_BITS && "Too many bits"); + uint32_t wordsAfter = _AP_N; + if (wordsAfter==1) { + assert(0); // return ap_private<_AP_W1, _AP_S, _AP_N1> (_AP_W1, VAL, _AP_S); + } else { + if (_AP_N1 == 1) { + assert(0); + // newVal[0] = VAL; + } else { + uint32_t i = 0; + for (; i < _AP_N1; ++i) + pVal[i] = that.pVal[i]; + for (; i < _AP_N; ++i) + pVal[i] = 0; + } + } + clearUnusedBits(); + } + + template + void cpZextOrTrunc(const ap_private<_AP_W1, _AP_S1, _AP_N1>& that) { + if (BitWidth > _AP_W1) + cpZext(that); + else if (BitWidth < _AP_W1) + cpTrunc(that); + else { + for (int i=0; i<_AP_N1; ++i) + pVal[i]=that.pVal[i]; + clearUnusedBits(); + } + } + + template + void cpSextOrTrunc(const ap_private<_AP_W1, _AP_S1, _AP_N1>& that) { + if (BitWidth > _AP_W1) + cpSext(that); + else if (BitWidth < _AP_W1) + cpTrunc(that); + else { + for (int i=0; i<_AP_N1; ++i) + pVal[i] = that.pVal[i]; + clearUnusedBits(); + } + } + + /// @name Value Characterization Functions + /// @{ + + /// @returns the total number of bits. + INLINE uint32_t getBitWidth() const { + return BitWidth; + } + + /// Here one word's bitwidth equals to that of uint64_t. + /// @returns the number of words to hold the integer value of this ap_private. + /// @brief Get the number of words. + INLINE uint32_t getNumWords() const { + return (BitWidth + APINT_BITS_PER_WORD - 1) / APINT_BITS_PER_WORD; + } + + /// This function returns the number of active bits which is defined as the + /// bit width minus the number of leading zeros. This is used in several + /// computations to see how "wide" the value is. + /// @brief Compute the number of active bits in the value + INLINE uint32_t getActiveBits() const { + uint32_t bits=BitWidth - countLeadingZeros(); + return bits?bits:1; + } + + + /// This method attempts to return the value of this ap_private as a zero extended + /// uint64_t. The bitwidth must be <= 64 or the value must fit within a + /// uint64_t. Otherwise an assertion will result. + /// @brief Get zero extended value + INLINE uint64_t getZExtValue() const { + assert(getActiveBits() <= 64 && "Too many bits for uint64_t"); + return *pVal; + } + + /// This method attempts to return the value of this ap_private as a sign extended + /// int64_t. The bit width must be <= 64 or the value must fit within an + /// int64_t. Otherwise an assertion will result. + /// @brief Get sign extended value + INLINE int64_t getSExtValue() const { + assert(getActiveBits() <= 64 && "Too many bits for int64_t"); + return int64_t(pVal[0]); + } + + /// This method determines how many bits are required to hold the ap_private + /// equivalent of the string given by \p str of length \p slen. + /// @brief Get bits required for string value. + static uint32_t getBitsNeeded(const char* str, uint32_t slen, uint8_t radix); + + /// countLeadingZeros - This function is an ap_private version of the + /// countLeadingZeros_{32,64} functions in MathExtras.h. It counts the number + /// of zeros from the most significant bit to the first one bit. + /// @returns BitWidth if the value is zero. + /// @returns the number of zeros from the most significant bit to the first + /// one bits. + INLINE uint32_t countLeadingZeros() const ; + + /// countLeadingOnes - This function counts the number of contiguous 1 bits + /// in the high order bits. The count stops when the first 0 bit is reached. + /// @returns 0 if the high order bit is not set + /// @returns the number of 1 bits from the most significant to the least + /// @brief Count the number of leading one bits. + INLINE uint32_t countLeadingOnes() const ; + + /// countTrailingZeros - This function is an ap_private version of the + /// countTrailingZoers_{32,64} functions in MathExtras.h. It counts + /// the number of zeros from the least significant bit to the first set bit. + /// @returns BitWidth if the value is zero. + /// @returns the number of zeros from the least significant bit to the first + /// one bit. + /// @brief Count the number of trailing zero bits. + INLINE uint32_t countTrailingZeros() const ; + + /// countPopulation - This function is an ap_private version of the + /// countPopulation_{32,64} functions in MathExtras.h. It counts the number + /// of 1 bits in the ap_private value. + /// @returns 0 if the value is zero. + /// @returns the number of set bits. + /// @brief Count the number of bits set. + INLINE uint32_t countPopulation() const { + uint32_t Count = 0; + for (uint32_t i = 0; i<_AP_N-1 ; ++i) + Count += CountPopulation_64(pVal[i]); + Count += CountPopulation_64(pVal[_AP_N-1]&mask); + return Count; + } + + /// @} + /// @name Conversion Functions + /// @{ + + /// This is used internally to convert an ap_private to a string. + /// @brief Converts an ap_private to a std::string + INLINE std::string toString(uint8_t radix, bool wantSigned) const + ; + + /// Considers the ap_private to be unsigned and converts it into a string in the + /// radix given. The radix can be 2, 8, 10 or 16. + /// @returns a character interpretation of the ap_private + /// @brief Convert unsigned ap_private to string representation. + INLINE std::string toStringUnsigned(uint8_t radix = 10) const { + return toString(radix, false); + } + + /// Considers the ap_private to be unsigned and converts it into a string in the + /// radix given. The radix can be 2, 8, 10 or 16. + /// @returns a character interpretation of the ap_private + /// @brief Convert unsigned ap_private to string representation. + INLINE std::string toStringSigned(uint8_t radix = 10) const { + return toString(radix, true); + } + + /// @returns a byte-swapped representation of this ap_private Value. + INLINE ap_private byteSwap() const ; + + /// @brief Converts this ap_private to a double value. + INLINE double roundToDouble(bool isSigned) const ; + + /// @brief Converts this unsigned ap_private to a double value. + INLINE double roundToDouble() const { + return roundToDouble(false); + } + + /// @brief Converts this signed ap_private to a double value. + INLINE double signedRoundToDouble() const { + return roundToDouble(true); + } + + /// The conversion does not do a translation from integer to double, it just + /// re-interprets the bits as a double. Note that it is valid to do this on + /// any bit width. Exactly 64 bits will be translated. + /// @brief Converts ap_private bits to a double + INLINE double bitsToDouble() const { + union { + uint64_t __I; + double __D; + } __T; + __T.__I = pVal[0]; + return __T.__D; + } + + /// The conversion does not do a translation from integer to float, it just + /// re-interprets the bits as a float. Note that it is valid to do this on + /// any bit width. Exactly 32 bits will be translated. + /// @brief Converts ap_private bits to a double + INLINE float bitsToFloat() const { + union { + uint32_t __I; + float __F; + } __T; + __T.__I = uint32_t(pVal[0]); + return __T.__F; + } + + /// The conversion does not do a translation from double to integer, it just + /// re-interprets the bits of the double. Note that it is valid to do this on + /// any bit width but bits from V may get truncated. + /// @brief Converts a double to ap_private bits. + INLINE ap_private& doubleToBits(double __V) { + union { + uint64_t __I; + double __D; + } __T; + __T.__D = __V; + pVal[0] = __T.__I; + return *this; + } + + /// The conversion does not do a translation from float to integer, it just + /// re-interprets the bits of the float. Note that it is valid to do this on + /// any bit width but bits from V may get truncated. + /// @brief Converts a float to ap_private bits. + INLINE ap_private& floatToBits(float __V) { + union { + uint32_t __I; + float __F; + } __T; + __T.__F = __V; + pVal[0] = __T.__I; + } + + //Reduce operation + //----------------------------------------------------------- + INLINE bool and_reduce() const { + return isMaxValue(); + } + + INLINE bool nand_reduce() const { + return isMinValue(); + } + + INLINE bool or_reduce() const { + return (bool)countPopulation(); + } + + INLINE bool nor_reduce() const { + return countPopulation()==0; + } + + INLINE bool xor_reduce() const { + unsigned int i=countPopulation(); + return (i%2)?true:false; + } + + INLINE bool xnor_reduce() const { + unsigned int i=countPopulation(); + return (i%2)?false:true; + } + INLINE std::string to_string(uint8_t radix=16, bool sign=false) const { + return toString(radix, radix==10?_AP_S:sign); + } +}; + +template +INLINE bool operator==(uint64_t V1, const ap_private<_AP_W, _AP_S, _AP_N>& V2) { + return V2 == V1; +} + +template +INLINE bool operator!=(uint64_t V1, const ap_private<_AP_W, _AP_S, _AP_N>& V2) { + return V2 != V1; +} + +namespace ap_private_ops { + enum {APINT_BITS_PER_WORD=64}; + /// @brief Determine the smaller of two ap_privates considered to be signed. + template + INLINE ap_private<_AP_W, _AP_S||_AP_S1, _AP_N> smin(const ap_private<_AP_W, _AP_S, _AP_N> &LHS, const ap_private<_AP_W, _AP_S1, _AP_N> &RHS) { + return LHS.slt(RHS) ? LHS : RHS; + } + + /// @brief Determine the larger of two ap_privates considered to be signed. + template + INLINE ap_private<_AP_W, _AP_S||_AP_S1, _AP_N> smax(const ap_private<_AP_W, _AP_S, _AP_N> &LHS, const ap_private<_AP_W, _AP_S1, _AP_N> &RHS) { + return LHS.sgt(RHS) ? LHS : RHS; + } + + /// @brief Determine the smaller of two ap_privates considered to be signed. + template + INLINE ap_private<_AP_W, _AP_S||_AP_S1, _AP_N> umin(const ap_private<_AP_W, _AP_S, _AP_N> &LHS, const ap_private<_AP_W, _AP_S1, _AP_N> &RHS) { + return LHS.ult(RHS) ? LHS : RHS; + } + + /// @brief Determine the larger of two ap_privates considered to be unsigned. + template + INLINE ap_private<_AP_W, _AP_S||_AP_S1, _AP_N> umax(const ap_private<_AP_W, _AP_S, _AP_N> &LHS, const ap_private<_AP_W, _AP_S1, _AP_N> &RHS) { + return LHS.ugt(RHS) ? LHS : RHS; + } + + /// @brief Check if the specified ap_private has a N-bits integer value. + template + INLINE bool isIntN(uint32_t __N, const ap_private<_AP_W, _AP_S, _AP_N>& APIVal) { + return APIVal.isIntN(__N); + } + + /// @returns true if the argument ap_private value is a sequence of ones + /// starting at the least significant bit with the remainder zero. + template + INLINE bool isMask(uint32_t numBits, const ap_private<_AP_W, _AP_S, _AP_N>& APIVal) { + return APIVal.getBoolValue() && ((APIVal + ap_private<_AP_W, _AP_S, _AP_N>(numBits,1)) & APIVal) == 0; + } + + /// @returns true if the argument ap_private value contains a sequence of ones + /// with the remainder zero. + template + INLINE bool isShiftedMask(uint32_t numBits, const ap_private<_AP_W, _AP_S, _AP_N>& APIVal) { + return isMask(numBits, (APIVal - ap_private<_AP_W, _AP_S, _AP_N>(numBits,1)) | APIVal); + } + + /// @returns a byte-swapped representation of the specified ap_private Value. + template INLINE ap_private<_AP_W, _AP_S, _AP_N> byteSwap(const ap_private<_AP_W, _AP_S, _AP_N>& APIVal) { + return APIVal.byteSwap(); + } + + /// @returns the floor log base 2 of the specified ap_private value. + template INLINE uint32_t logBase2(const ap_private<_AP_W, _AP_S, _AP_N>& APIVal) { + return APIVal.logBase2(); + } + + /// GreatestCommonDivisor - This function returns the greatest common + /// divisor of the two ap_private values using Enclid's algorithm. + /// @returns the greatest common divisor of Val1 and Val2 + /// @brief Compute GCD of two ap_private values. + template INLINE ap_private<_AP_W, _AP_S, _AP_N> GreatestCommonDivisor(const ap_private<_AP_W, _AP_S, _AP_N>& Val1, const ap_private<_AP_W, _AP_S, _AP_N>& Val2) + ; + + /// Treats the ap_private as an unsigned value for conversion purposes. + /// @brief Converts the given ap_private to a double value. + template INLINE double Roundap_privateToDouble(const ap_private<_AP_W, _AP_S, _AP_N>& APIVal) { + return APIVal.roundToDouble(); + } + + /// Treats the ap_private as a signed value for conversion purposes. + /// @brief Converts the given ap_private to a double value. + template INLINE double RoundSignedap_privateToDouble(const ap_private<_AP_W, _AP_S, _AP_N>& APIVal) { + return APIVal.signedRoundToDouble(); + } + + /// @brief Converts the given ap_private to a float vlalue. + template INLINE float Roundap_privateToFloat(const ap_private<_AP_W, _AP_S, _AP_N>& APIVal) { + return float(Roundap_privateToDouble(APIVal)); + } + + /// Treast the ap_private as a signed value for conversion purposes. + /// @brief Converts the given ap_private to a float value. + template INLINE float RoundSignedap_privateToFloat(const ap_private<_AP_W, _AP_S, _AP_N>& APIVal) { + return float(APIVal.signedRoundToDouble()); + } + + /// RoundDoubleToap_private - This function convert a double value to an ap_private value. + /// @brief Converts the given double value into a ap_private. + template INLINE ap_private<_AP_W, _AP_S, _AP_N> RoundDoubleToap_private(double Double, uint32_t width) ; + + /// RoundFloatToap_private - Converts a float value into an ap_private value. + /// @brief Converts a float value into a ap_private. + template INLINE ap_private<_AP_W, _AP_S, _AP_N> RoundFloatToap_private(float Float, uint32_t width) { + return RoundDoubleToap_private<_AP_W, _AP_S, _AP_N>(double(Float), width); + } + + /// Arithmetic right-shift the ap_private by shiftAmt. + /// @brief Arithmetic right-shift function. + template INLINE ap_private<_AP_W, _AP_S, _AP_N> ashr(const ap_private<_AP_W, _AP_S, _AP_N>& LHS, uint32_t shiftAmt) { + return LHS.ashr(shiftAmt); + } + + /// Logical right-shift the ap_private by shiftAmt. + /// @brief Logical right-shift function. + template INLINE ap_private<_AP_W, _AP_S, _AP_N> lshr(const ap_private<_AP_W, _AP_S, _AP_N>& LHS, uint32_t shiftAmt) { + return LHS.lshr(shiftAmt); + } + + /// Left-shift the ap_private by shiftAmt. + /// @brief Left-shift function. + template INLINE ap_private<_AP_W, _AP_S, _AP_N> shl(const ap_private<_AP_W, _AP_S, _AP_N>& LHS, uint32_t shiftAmt) { + return LHS.shl(shiftAmt); + } + + /// Signed divide ap_private LHS by ap_private RHS. + /// @brief Signed division function for ap_private. + template + INLINE ap_private<_AP_W, _AP_S||_AP_S1, _AP_N> sdiv(const ap_private<_AP_W, _AP_S, _AP_N>& LHS, const ap_private<_AP_W, _AP_S1, _AP_N>& RHS) { + return LHS.sdiv(RHS); + } + + /// Unsigned divide ap_private LHS by ap_private RHS. + /// @brief Unsigned division function for ap_private. + template + INLINE ap_private<_AP_W, _AP_S||_AP_S1, _AP_N> udiv(const ap_private<_AP_W, _AP_S, _AP_N>& LHS, const ap_private<_AP_W, _AP_S1, _AP_N>& RHS) { + return LHS.udiv(RHS); + } + + /// Signed remainder operation on ap_private. + /// @brief Function for signed remainder operation. + template + INLINE ap_private<_AP_W, _AP_S||_AP_S1, _AP_N> srem(const ap_private<_AP_W, _AP_S, _AP_N>& LHS, const ap_private<_AP_W, _AP_S1, _AP_N>& RHS) { + return LHS.srem(RHS); + } + + /// Unsigned remainder operation on ap_private. + /// @brief Function for unsigned remainder operation. + template + INLINE ap_private<_AP_W, _AP_S||_AP_S1, _AP_N> urem(const ap_private<_AP_W, _AP_S, _AP_N>& LHS, const ap_private<_AP_W, _AP_S1, _AP_N>& RHS) { + return LHS.urem(RHS); + } + + /// Performs multiplication on ap_private values. + /// @brief Function for multiplication operation. + template + INLINE ap_private<_AP_W, _AP_S||_AP_S1, _AP_N> mul(const ap_private<_AP_W, _AP_S, _AP_N>& LHS, const ap_private<_AP_W, _AP_S1, _AP_N>& RHS) { + return LHS * RHS; + } + + /// Performs addition on ap_private values. + /// @brief Function for addition operation. + template + INLINE ap_private<_AP_W, _AP_S||_AP_S1, _AP_N> add(const ap_private<_AP_W, _AP_S, _AP_N>& LHS, const ap_private<_AP_W, _AP_S1, _AP_N>& RHS) { + return LHS + RHS; + } + + /// Performs subtraction on ap_private values. + /// @brief Function for subtraction operation. + template + INLINE ap_private<_AP_W, _AP_S||_AP_S1, _AP_N> sub(const ap_private<_AP_W, _AP_S, _AP_N>& LHS, const ap_private<_AP_W, _AP_S1, _AP_N>& RHS) { + return LHS - RHS; + } + + /// Performs bitwise AND operation on ap_private LHS and + /// ap_private RHS. + /// @brief Bitwise AND function for ap_private. + template + INLINE ap_private<_AP_W, _AP_S||_AP_S1, _AP_N> And(const ap_private<_AP_W, _AP_S, _AP_N>& LHS, const ap_private<_AP_W, _AP_S1, _AP_N>& RHS) { + return LHS & RHS; + } + + /// Performs bitwise OR operation on ap_private LHS and ap_private RHS. + /// @brief Bitwise OR function for ap_private. + template + INLINE ap_private<_AP_W, _AP_S||_AP_S1, _AP_N> Or(const ap_private<_AP_W, _AP_S, _AP_N>& LHS, const ap_private<_AP_W, _AP_S1, _AP_N>& RHS) { + return LHS | RHS; + } + + /// Performs bitwise XOR operation on ap_private. + /// @brief Bitwise XOR function for ap_private. + template + INLINE ap_private<_AP_W, _AP_S||_AP_S1, _AP_N> Xor(const ap_private<_AP_W, _AP_S, _AP_N>& LHS, const ap_private<_AP_W, _AP_S1, _AP_N>& RHS) { + return LHS ^ RHS; + } + + /// Performs a bitwise complement operation on ap_private. + /// @brief Bitwise complement function. + template INLINE ap_private<_AP_W, _AP_S, _AP_N> Not(const ap_private<_AP_W, _AP_S, _AP_N>& APIVal) { + return ~APIVal; + } + + template void clearUnusedBits(uint64_t& msw) { + // Compute how many bits are used in the final word + // uint32_t wordBits = APIVal.getBitWidth() & 0x3f; + if (wordBits == 0) + // If all bits are used, we want to leave the value alone. This also + // avoids the undefined behavior of >> when the shfit is the same size as + // the word size (64). + return; + + // Mask out the hight bits. + uint64_t mask = ~uint64_t(0ULL) >> (64 /*ap_private::APINT_BITS_PER_WORD */- wordBits); + msw &= mask; + } + template <> INLINE void clearUnusedBits<1>(uint64_t& msw) { + uint64_t mask = ~uint64_t(0ULL) >> (64 /*ap_private::APINT_BITS_PER_WORD */- 1); + msw &= mask; + } + template void clearUnusedBits(int64_t& msw) { + // Compute how many bits are used in the final word + // uint32_t wordBits = APIVal.getBitWidth() & 0x3f; + if (wordBits == 0) + // If all bits are used, we want to leave the value alone. This also + // avoids the undefined behavior of >> when the shfit is the same size as + // the word size (64). + return; + + // Mask out the hight bits. + uint64_t mask = ~uint64_t(0ULL) >> (64 /*ap_private::APINT_BITS_PER_WORD */- wordBits); + msw &= mask; + } + template <> INLINE void clearUnusedBits<1>(int64_t& msw) { + uint64_t mask = ~uint64_t(0ULL) >> (64 /*ap_private::APINT_BITS_PER_WORD */- 1); + msw &= mask; + } + // template + template + INLINE ap_private<_AP_W, _AP_S> ashr(const ap_private<_AP_W, _AP_S>& a) { + return ashr(a, shiftAmt); + } + + template + INLINE ap_private<_AP_W, _AP_S> lshr(const ap_private<_AP_W, _AP_S>& a) { + return lshr(a, shiftAmt); + } + + template + INLINE ap_private<_AP_W, true> ashr(const ap_private<_AP_W, true, 1>& a) { + enum {APINT_BITS_PER_WORD=64, excess_bits=APINT_BITS_PER_WORD-_AP_W}; + static const uint64_t sign_bit = (1ULL<<(_AP_W-1)); + static const uint64_t sign_ext_mask = (_AP_W-shiftAmt>0)?~0ULL<<(APINT_BITS_PER_WORD-_AP_W+shiftAmt):~0ULL; + return ap_private<_AP_W, true>((((int64_t)a.VAL) >> (shiftAmt)) | (a.VAL & sign_bit? sign_ext_mask : 0ULL)); + } + + template + INLINE ap_private<_AP_W, false> ashr(const ap_private<_AP_W, false, 1>& a) { + return ap_private<_AP_W, false>((a.VAL) >> (shiftAmt)); + } + + template + INLINE ap_private<_AP_W, _AP_S> lshr(const ap_private<_AP_W, _AP_S, 1>& a) { + static const uint64_t mask = ~0ULL<<_AP_W; + return ap_private<_AP_W, _AP_S>((a.VAL&mask) >> (shiftAmt)); + } + + template + INLINE ap_private<_AP_W-shiftAmt, _AP_S> shr(const ap_private<_AP_W, _AP_S>& a) { + return ap_private<_AP_W-shiftAmt, _AP_S>((a.VAL) >> (shiftAmt)); + } + + template + INLINE ap_private<_AP_W+shiftAmt, _AP_S> shl(const ap_private<_AP_W, _AP_S>& a) { + return ap_private<_AP_W+shiftAmt, _AP_S>((a.VAL) << (shiftAmt)); + } + + template + INLINE bool get(const ap_private<_AP_W, _AP_S, 1>& a) { + unsigned shift = (index%APINT_BITS_PER_WORD); + static const uint64_t mask=1ULL << (shift); + return ((mask & a.VAL) != 0); + } + + template + INLINE bool get(const ap_private<_AP_W, _AP_S>& a) { + static const uint64_t mask=1ULL << (index&0x3f); + return ((mask & a.pVal[(index)>>6]) != 0); + } + + template + INLINE void set(ap_private<_AP_W, _AP_S, 1>& a) { + const uint64_t mask = ~0ULL >> (lsb) << (APINT_BITS_PER_WORD-msb+lsb-1)>>(APINT_BITS_PER_WORD-msb-1); + a.VAL |= mask; + } + + template + INLINE void clear(ap_private<_AP_W, _AP_S, 1>& a) { + static const uint64_t mask = ~(~0ULL >> (lsb) <<(APINT_BITS_PER_WORD-msb+lsb-1) >> (APINT_BITS_PER_WORD-msb-1)); + a.VAL &= mask; + } + + template + INLINE void set(ap_private<_AP_W, _AP_S>& a) { + enum { APINT_BITS_PER_WORD=64, + lsb_word = lsb_index /APINT_BITS_PER_WORD, + msb_word = msb_index / APINT_BITS_PER_WORD, + msb = msb_index % APINT_BITS_PER_WORD, + lsb=lsb_index % APINT_BITS_PER_WORD}; + if (msb_word==lsb_word) { + const uint64_t mask = ~0ULL >> (lsb) << (APINT_BITS_PER_WORD-msb+lsb-1)>>(APINT_BITS_PER_WORD-msb-1); + a.pVal[msb_word] |= mask; + } else { + const uint64_t lsb_mask = ~0ULL >> (lsb) << (lsb); + const uint64_t msb_mask = ~0ULL << (APINT_BITS_PER_WORD-msb-1)>>(APINT_BITS_PER_WORD-msb-1); + a.pVal[lsb_word] |=lsb_mask; + for (int i=lsb_word+1; i + INLINE void clear(ap_private<_AP_W, _AP_S>& a) { + enum { APINT_BITS_PER_WORD=64, + lsb_word = lsb_index /APINT_BITS_PER_WORD, + msb_word = msb_index / APINT_BITS_PER_WORD, + msb = msb_index % APINT_BITS_PER_WORD, + lsb=lsb_index % APINT_BITS_PER_WORD}; + if (msb_word == lsb_word) { + const uint64_t mask = ~(~0ULL >> (lsb) << (APINT_BITS_PER_WORD-msb+lsb-1)>>(APINT_BITS_PER_WORD-msb-1)); + a.pVal[msb_word] &= mask; + } else { + const uint64_t lsb_mask = ~(~0ULL >> (lsb) << (lsb)); + const uint64_t msb_mask = ~(~0ULL << (APINT_BITS_PER_WORD-msb-1)>>(APINT_BITS_PER_WORD-msb-1)); + a.pVal[lsb_word] &=lsb_mask; + for (int i=lsb_word+1; i + INLINE void set(ap_private<_AP_W, _AP_S, 1>& a) { + static const uint64_t mask=1ULL << (index); + a.VAL |= mask; + a.clearUnusedBits(); + } + + template + INLINE void clear(ap_private<_AP_W, _AP_S, 1>& a) { + static const uint64_t mask=~(1ULL << (index)); + a.VAL &= mask; + a.clearUnusedBits(); + } + + template + INLINE void set(ap_private<_AP_W, _AP_S>& a) { + enum { APINT_BITS_PER_WORD=64, word = index/APINT_BITS_PER_WORD}; + static const uint64_t mask=1ULL << (index%APINT_BITS_PER_WORD); + a.pVal[word] |= mask; + a.clearUnusedBits(); + } + + template + INLINE void clear(ap_private<_AP_W, _AP_S>& a) { + enum { APINT_BITS_PER_WORD=64, word = index/APINT_BITS_PER_WORD}; + static const uint64_t mask=~(1ULL << (index%APINT_BITS_PER_WORD)); + a.pVal[word] &= mask; + a.clearUnusedBits(); + } + + template + INLINE bool isNegative(const ap_private<_AP_W, false>& a) { + return false; + } + + template + INLINE bool isNegative(const ap_private<_AP_W, true, 1>& a) { + static const uint64_t sign_mask = (1ULL << (_AP_W-1)); + return ((sign_mask & a.VAL) != 0); + } + + template + INLINE bool isNegative(const ap_private<_AP_W, true>& a) { + enum {APINT_BITS_PER_WORD=64,_AP_N=(_AP_W+APINT_BITS_PER_WORD-1)/APINT_BITS_PER_WORD}; + static const uint64_t sign_mask = (1ULL << (_AP_W%APINT_BITS_PER_WORD-1)); + return sign_mask & a.pVal[_AP_N-1]; + } +} // End of ap_private_ops namespace + +/// @brief Check if the specified ap_private has a N-bits integer value. +template +INLINE bool isIntN(uint32_t __N, const ap_private<_AP_W, _AP_S, _AP_N>& APIVal) { + return APIVal.isIntN(__N); +} + +/// @returns true if the argument ap_private value is a sequence of ones +/// starting at the least significant bit with the remainder zero. +template +INLINE bool isMask(uint32_t numBits, const ap_private<_AP_W, _AP_S, _AP_N>& APIVal) { + return APIVal.getBoolValue() && ((APIVal + ap_private<_AP_W, _AP_S, _AP_N>(numBits,1)) & APIVal) == 0; +} + +/// @returns true if the argument ap_private value contains a sequence of ones +/// with the remainder zero. +template +INLINE bool isShiftedMask(uint32_t numBits, const ap_private<_AP_W, _AP_S, _AP_N>& APIVal) { + return isMask(numBits, (APIVal - ap_private<_AP_W, _AP_S, _AP_N>(numBits,1)) | APIVal); +} + +#if 0 +/// add_1 - This function adds a single "digit" integer, y, to the multiple +/// "digit" integer array, x[]. x[] is modified to reflect the addition and +/// 1 is returned if there is a carry out, otherwise 0 is returned. +/// @returns the carry of the addition. +static bool add_1(uint64_t dest[], uint64_t x[], uint32_t len, uint64_t y) { + for (uint32_t i = 0; i < len; ++i) { + dest[i] = y + x[i]; + if (dest[i] < y) + y = 1; // Carry one to next digit. + else { + y = 0; // No need to carry so exit early + break; + } + } + return (y != 0); +} +#endif + +#if 0 +/// add - This function adds the integer array x to the integer array Y and +/// places the result in dest. +/// @returns the carry out from the addition +/// @brief General addition of 64-bit integer arrays +static bool add(uint64_t *dest, const uint64_t *x, const uint64_t *y, + uint32_t destlen, uint32_t xlen, uint32_t ylen, bool xsigned, bool ysigned) { + bool carry = false; + uint32_t len = AESL_std::min(xlen, ylen); + uint32_t i; + for (i = 0; i< len && i < destlen; ++i) { + uint64_t limit = AESL_std::min(x[i],y[i]); // must come first in case dest == x + dest[i] = x[i] + y[i] + carry; + carry = dest[i] < limit || (carry && dest[i] == limit); + } + if (xlen > ylen) { + const uint64_t yext = xsigned && int64_t(y[ylen-1])<0 ? -1 : 0; + for (i=ylen; i< xlen && i < destlen; i++) { + uint64_t limit = AESL_std::min(x[i], yext); + dest[i] = x[i] + yext + carry; + carry = (dest[i] < limit)||(carry && dest[i] == x[i]); + } + } else if (ylen> xlen) { + const uint64_t xext = ysigned && int64_t(x[xlen-1])<0 ? -1 : 0; + for (i=xlen; i< ylen && i < destlen; i++) { + uint64_t limit = AESL_std::min(xext, y[i]); + dest[i] = xext + y[i] + carry; + carry = (dest[i] < limit)||(carry && dest[i] == y[i]); + } + } + return carry; +} +#endif + +#if 0 +/// @returns returns the borrow out. +/// @brief Generalized subtraction of 64-bit integer arrays. +static bool sub(uint64_t *dest, const uint64_t *x, const uint64_t *y, + uint32_t destlen, uint32_t xlen, uint32_t ylen, bool xsigned, bool ysigned) { + bool borrow = false; + uint32_t i; + uint32_t len = AESL_std::min(xlen, ylen); + for (i = 0; i < len && i < destlen; ++i) { + uint64_t x_tmp = borrow ? x[i] - 1 : x[i]; + borrow = y[i] > x_tmp || (borrow && x[i] == 0); + dest[i] = x_tmp - y[i]; + } + if (xlen > ylen) { + const uint64_t yext = ysigned && int64_t(y[ylen-1])<0 ? -1 : 0; + for (i=ylen; i< xlen && i < destlen; i++) { + uint64_t x_tmp = borrow ? x[i] - 1 : x[i]; + borrow = yext > x_tmp || (borrow && x[i] == 0); + dest[i] = x_tmp - yext; + } + } else if (ylen> xlen) { + const uint64_t xext = xsigned && int64_t(x[xlen-1])<0 ? -1 : 0; + for (i=xlen; i< ylen && i < destlen; i++) { + uint64_t x_tmp = borrow ? xext - 1 : xext; + borrow = y[i] > x_tmp || (borrow && xext==0); + dest[i] = x_tmp - y[i]; + } + } + return borrow; +} +#endif + +/// Subtracts the RHS ap_private from this ap_private +/// @returns this, after subtraction +/// @brief Subtraction assignment operator. + +#if 0 +/// Multiplies an integer array, x by a a uint64_t integer and places the result +/// into dest. +/// @returns the carry out of the multiplication. +/// @brief Multiply a multi-digit ap_private by a single digit (64-bit) integer. +static uint64_t mul_1(uint64_t dest[], const uint64_t x[], uint32_t len, uint64_t y) { + // Split y into high 32-bit part (hy) and low 32-bit part (ly) + uint64_t ly = y & 0xffffffffULL, hy = (y) >> 32; + uint64_t carry = 0; + static const uint64_t two_power_32 = 1ULL << 32; + // For each digit of x. + for (uint32_t i = 0; i < len; ++i) { + // Split x into high and low words + uint64_t lx = x[i] & 0xffffffffULL; + uint64_t hx = (x[i]) >> 32; + // hasCarry - A flag to indicate if there is a carry to the next digit. + // hasCarry == 0, no carry + // hasCarry == 1, has carry + // hasCarry == 2, no carry and the calculation result == 0. + uint8_t hasCarry = 0; + dest[i] = carry + lx * ly; + // Determine if the add above introduces carry. + hasCarry = (dest[i] < carry) ? 1 : 0; + carry = hx * ly + ((dest[i]) >> 32) + (hasCarry ? two_power_32 : 0); + // The upper limit of carry can be (2^32 - 1)(2^32 - 1) + + // (2^32 - 1) + 2^32 = 2^64. + hasCarry = (!carry && hasCarry) ? 1 : (!carry ? 2 : 0); + + carry += (lx * hy) & 0xffffffffULL; + dest[i] = ((carry) << 32) | (dest[i] & 0xffffffffULL); + carry = (((!carry && hasCarry != 2) || hasCarry == 1) ? two_power_32 : 0) + + ((carry) >> 32) + ((lx * hy) >> 32) + hx * hy; + } + return carry; +} +#endif + +#if 0 +/// Multiplies integer array x by integer array y and stores the result into +/// the integer array dest. Note that dest's size must be >= xlen + ylen. +/// @brief Generalized multiplicate of integer arrays. +static void mul(uint64_t dest[], const uint64_t x[], uint32_t xlen, const uint64_t y[], + uint32_t ylen, uint32_t destlen) { + dest[xlen] = mul_1(dest, x, xlen, y[0]); + for (uint32_t i = 1; i < ylen; ++i) { + uint64_t ly = y[i] & 0xffffffffULL, hy = (y[i]) >> 32; + uint64_t carry = 0, lx = 0, hx = 0; + for (uint32_t j = 0; j < xlen; ++j) { + lx = x[j] & 0xffffffffULL; + hx = (x[j]) >> 32; + // hasCarry - A flag to indicate if has carry. + // hasCarry == 0, no carry + // hasCarry == 1, has carry + // hasCarry == 2, no carry and the calculation result == 0. + uint8_t hasCarry = 0; + uint64_t resul = carry + lx * ly; + hasCarry = (resul < carry) ? 1 : 0; + carry = (hasCarry ? (1ULL << 32) : 0) + hx * ly + ((resul) >> 32); + hasCarry = (!carry && hasCarry) ? 1 : (!carry ? 2 : 0); + carry += (lx * hy) & 0xffffffffULL; + resul = ((carry) << 32) | (resul & 0xffffffffULL); + dest[i+j] += resul; + carry = (((!carry && hasCarry != 2) || hasCarry == 1) ? (1ULL << 32) : 0)+ + ((carry) >> 32) + (dest[i+j] < resul ? 1 : 0) + + ((lx * hy) >> 32) + hx * hy; + } + dest[i+xlen] = carry; + } +} +#endif + + + +template +uint32_t ap_private<_AP_W, _AP_S, _AP_N>::getBitsNeeded(const char* str, uint32_t slen, uint8_t radix) { + assert(str != 0 && "Invalid value string"); + assert(slen > 0 && "Invalid string length"); + + // Each computation below needs to know if its negative + uint32_t isNegative = str[0] == '-'; + if (isNegative) { + slen--; + str++; + } + // For radixes of power-of-two values, the bits required is accurately and + // easily computed + if (radix == 2) + return slen + isNegative; + if (radix == 8) + return slen * 3 + isNegative; + if (radix == 16) + return slen * 4 + isNegative; + + // Otherwise it must be radix == 10, the hard case + assert(radix == 10 && "Invalid radix"); + + // Convert to the actual binary value. + //ap_private<_AP_W, _AP_S, _AP_N> tmp(sufficient, str, slen, radix); + + // Compute how many bits are required. + //return isNegative + tmp.logBase2() + 1; + return isNegative + slen * 4; +} + +template +uint32_t ap_private<_AP_W, _AP_S, _AP_N>::countLeadingZeros() const { + enum { msw_bits = (BitWidth % APINT_BITS_PER_WORD)?(BitWidth % APINT_BITS_PER_WORD):APINT_BITS_PER_WORD, + excessBits = APINT_BITS_PER_WORD - msw_bits }; + uint32_t Count = CountLeadingZeros_64(pVal[_AP_N-1]); + if (Count>=excessBits) + Count -= excessBits; + if (!pVal[_AP_N-1]) { + for (uint32_t i = _AP_N-1 ; i ; --i) { + if (!pVal[i-1]) + Count += APINT_BITS_PER_WORD; + else { + Count += CountLeadingZeros_64(pVal[i-1]); + break; + } + } + } + return Count; +} + +static uint32_t countLeadingOnes_64(uint64_t __V, uint32_t skip) { + uint32_t Count = 0; + if (skip) + (__V) <<= (skip); + while (__V && (__V & (1ULL << 63))) { + Count++; + (__V) <<= 1; + } + return Count; +} + +template +uint32_t ap_private<_AP_W, _AP_S, _AP_N>::countLeadingOnes() const { + if (isSingleWord()) + return countLeadingOnes_64(VAL, APINT_BITS_PER_WORD - BitWidth); + + uint32_t highWordBits = BitWidth % APINT_BITS_PER_WORD; + uint32_t shift = (highWordBits == 0 ? 0 : APINT_BITS_PER_WORD - highWordBits); + int i = _AP_N - 1; + uint32_t Count = countLeadingOnes_64(pVal[i], shift); + if (Count == highWordBits) { + for (i--; i >= 0; --i) { + if (pVal[i] == ~0ULL) + Count += APINT_BITS_PER_WORD; + else { + Count += countLeadingOnes_64(pVal[i], 0); + break; + } + } + } + return Count; +} + +template +INLINE uint32_t ap_private<_AP_W, _AP_S, _AP_N>::countTrailingZeros() const { + if (isSingleWord()) + return AESL_std::min(uint32_t(CountTrailingZeros_64(VAL)), BitWidth); + uint32_t Count = 0; + uint32_t i = 0; + for (; i < _AP_N && pVal[i] == 0; ++i) + Count += APINT_BITS_PER_WORD; + if (i < _AP_N) + Count += CountTrailingZeros_64(pVal[i]); + return AESL_std::min(Count, BitWidth); +} + +template +ap_private<_AP_W, _AP_S, _AP_N> ap_private<_AP_W, _AP_S, _AP_N>::byteSwap() const { + assert(BitWidth >= 16 && BitWidth % 16 == 0 && "Cannot byteswap!"); + if (BitWidth == 16) + return ap_private<_AP_W, _AP_S, _AP_N>(/*BitWidth,*/ ByteSwap_16(uint16_t(VAL))); + else if (BitWidth == 32) + return ap_private<_AP_W, _AP_S, _AP_N>(/*BitWidth,*/ ByteSwap_32(uint32_t(VAL))); + else if (BitWidth == 48) { + uint32_t Tmp1 = uint32_t((VAL) >> 16); + Tmp1 = ByteSwap_32(Tmp1); + uint16_t Tmp2 = uint16_t(VAL); + Tmp2 = ByteSwap_16(Tmp2); + return ap_private<_AP_W, _AP_S, _AP_N>(/*BitWidth,*/ ((uint64_t(Tmp2)) << 32) | Tmp1); + } else if (BitWidth == 64) + return ap_private<_AP_W, _AP_S, _AP_N>(/*BitWidth,*/ ByteSwap_64(VAL)); + else { + ap_private<_AP_W, _AP_S, _AP_N> Result(0); + char *pByte = (char*)Result.pVal; + for (uint32_t i = 0; i < BitWidth / APINT_WORD_SIZE / 2; ++i) { + char Tmp = pByte[i]; + pByte[i] = pByte[BitWidth / APINT_WORD_SIZE - 1 - i]; + pByte[BitWidth / APINT_WORD_SIZE - i - 1] = Tmp; + } + return Result; + } +} + +template +ap_private<_AP_W, _AP_S, _AP_N> ap_private_ops::GreatestCommonDivisor(const ap_private<_AP_W, _AP_S, _AP_N>& API1, const ap_private<_AP_W, _AP_S, _AP_N>& API2) { + ap_private<_AP_W, _AP_S, _AP_N> __A = API1, __B = API2; + while (!!__B) { + ap_private<_AP_W, _AP_S, _AP_N> __T = __B; + __B = ap_private_ops::urem(__A, __B); + __A = __T; + } + return __A; +} + +template +ap_private<_AP_W, _AP_S, _AP_N> ap_private_ops::RoundDoubleToap_private(double Double, uint32_t width) { + union { + double __D; + uint64_t __I; + } __T; + __T.__D = Double; + + // Get the sign bit from the highest order bit + bool isNeg = (__T.__I) >> 63; + + // Get the 11-bit exponent and adjust for the 1023 bit bias + int64_t exp = (((__T.__I) >> 52) & 0x7ffULL) - 1023; + + // If the exponent is negative, the value is < 0 so just return 0. + if (exp < 0) + return ap_private<_AP_W, _AP_S, _AP_N>(width, 0u); + + // Extract the mantissa by clearing the top 12 bits (sign + exponent). + uint64_t mantissa = (__T.__I & (~0ULL >> 12)) | 1ULL << 52; + + // If the exponent doesn't shift all bits out of the mantissa + if (exp < 52) + return isNeg ? -ap_private<_AP_W, _AP_S, _AP_N>(width, (mantissa) >> (52 - exp)) : + ap_private<_AP_W, _AP_S, _AP_N>((mantissa) >> (52 - exp)); + + // If the client didn't provide enough bits for us to shift the mantissa into + // then the result is undefined, just return 0 + if (width <= exp - 52) + return ap_private<_AP_W, _AP_S, _AP_N>(width, 0); + + // Otherwise, we have to shift the mantissa bits up to the right location + ap_private<_AP_W, _AP_S, _AP_N> Tmp(width, mantissa); + Tmp = Tmp.shl(exp - 52); + return isNeg ? -Tmp : Tmp; +} + +/// RoundToDouble - This function convert this ap_private to a double. +/// The layout for double is as following (IEEE Standard 754): +/// -------------------------------------- +/// | Sign Exponent Fraction Bias | +/// |-------------------------------------- | +/// | 1[63] 11[62-52] 52[51-00] 1023 | +/// -------------------------------------- +template +double ap_private<_AP_W, _AP_S, _AP_N>::roundToDouble(bool isSigned) const { + + // Handle the simple case where the value is contained in one uint64_t. + if (isSingleWord() || getActiveBits() <= APINT_BITS_PER_WORD) { + uint64_t val; + if (isSingleWord()) val = VAL; + else val = pVal[0]; + if (isSigned) { + int64_t sext = ((int64_t(val)) << (64-BitWidth)) >> (64-BitWidth); + return double(sext); + } else + return double(val); + } + + // Determine if the value is negative. + bool isNeg = isSigned ? (*this)[BitWidth-1] : false; + + // Construct the absolute value if we're negative. + ap_private<_AP_W, _AP_S, _AP_N> Tmp(isNeg ? -(*this) : (*this)); + + // Figure out how many bits we're using. + uint32_t n = Tmp.getActiveBits(); + + // The exponent (without bias normalization) is just the number of bits + // we are using. Note that the sign bit is gone since we constructed the + // absolute value. + uint64_t exp = n; + + // Return infinity for exponent overflow + if (exp > 1023) { + if (!isSigned || !isNeg) + return std::numeric_limits::infinity(); + else + return -std::numeric_limits::infinity(); + } + exp += 1023; // Increment for 1023 bias + + // Number of bits in mantissa is 52. To obtain the mantissa value, we must + // extract the high 52 bits from the correct words in pVal. + uint64_t mantissa; + unsigned hiWord = whichWord(n-1); + if (hiWord == 0) { + mantissa = Tmp.pVal[0]; + if (n > 52) + (mantissa) >>= (n - 52); // shift down, we want the top 52 bits. + } else { + assert(hiWord > 0 && "High word is negative?"); + uint64_t hibits = (Tmp.pVal[hiWord]) << (52 - n % APINT_BITS_PER_WORD); + uint64_t lobits = (Tmp.pVal[hiWord-1]) >> (11 + n % APINT_BITS_PER_WORD); + mantissa = hibits | lobits; + } + + // The leading bit of mantissa is implicit, so get rid of it. + uint64_t sign = isNeg ? (1ULL << (APINT_BITS_PER_WORD - 1)) : 0; + union { + double __D; + uint64_t __I; + } __T; + __T.__I = sign | ((exp) << 52) | mantissa; + return __T.__D; +} + +// Square Root - this method computes and returns the square root of "this". +// Three mechanisms are used for computation. For small values (<= 5 bits), +// a table lookup is done. This gets some performance for common cases. For +// values using less than 52 bits, the value is converted to double and then +// the libc sqrt function is called. The result is rounded and then converted +// back to a uint64_t which is then used to construct the result. Finally, +// the Babylonian method for computing square roots is used. +template +ap_private<_AP_W, _AP_S, _AP_N> ap_private<_AP_W, _AP_S, _AP_N>::sqrt() const { + + // Determine the magnitude of the value. + uint32_t magnitude = getActiveBits(); + + // Use a fast table for some small values. This also gets rid of some + // rounding errors in libc sqrt for small values. + if (magnitude <= 5) { + static const uint8_t results[32] = { + /* 0 */ 0, + /* 1- 2 */ 1, 1, + /* 3- 6 */ 2, 2, 2, 2, + /* 7-12 */ 3, 3, 3, 3, 3, 3, + /* 13-20 */ 4, 4, 4, 4, 4, 4, 4, 4, + /* 21-30 */ 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, + /* 31 */ 6 + }; + return ap_private<_AP_W, _AP_S, _AP_N>(/*BitWidth,*/ results[ (isSingleWord() ? VAL : pVal[0]) ]); + } + + // If the magnitude of the value fits in less than 52 bits (the precision of + // an IEEE double precision floating point value), then we can use the + // libc sqrt function which will probably use a hardware sqrt computation. + // This should be faster than the algorithm below. + if (magnitude < 52) { +#ifdef _MSC_VER + // Amazingly, VC++ doesn't have round(). + return ap_private<_AP_W, _AP_S, _AP_N>(/*BitWidth,*/ + uint64_t(::sqrt(double(isSingleWord()?VAL:pVal[0]))) + 0.5); +#else + return ap_private<_AP_W, _AP_S, _AP_N>(/*BitWidth,*/ + uint64_t(::round(::sqrt(double(isSingleWord()?VAL:pVal[0]))))); +#endif + } + + // Okay, all the short cuts are exhausted. We must compute it. The following + // is a classical Babylonian method for computing the square root. This code + // was adapted to APINt from a wikipedia article on such computations. + // See http://www.wikipedia.org/ and go to the page named + // Calculate_an_integer_square_root. + uint32_t nbits = BitWidth, i = 4; + ap_private<_AP_W, _AP_S, _AP_N> testy(16); + ap_private<_AP_W, _AP_S, _AP_N> x_old(/*BitWidth,*/ 1); + ap_private<_AP_W, _AP_S, _AP_N> x_new(0); + ap_private<_AP_W, _AP_S, _AP_N> two(/*BitWidth,*/ 2); + + // Select a good starting value using binary logarithms. + for (;; i += 2, testy = testy.shl(2)) + if (i >= nbits || this->ule(testy)) { + x_old = x_old.shl(i / 2); + break; + } + + // Use the Babylonian method to arrive at the integer square root: + for (;;) { + x_new = (this->udiv(x_old) + x_old).udiv(two); + if (x_old.ule(x_new)) + break; + x_old = x_new; + } + + // Make sure we return the closest approximation + // NOTE: The rounding calculation below is correct. It will produce an + // off-by-one discrepancy with results from pari/gp. That discrepancy has been + // determined to be a rounding issue with pari/gp as it begins to use a + // floating point representation after 192 bits. There are no discrepancies + // between this algorithm and pari/gp for bit widths < 192 bits. + ap_private<_AP_W, _AP_S, _AP_N> square(x_old * x_old); + ap_private<_AP_W, _AP_S, _AP_N> nextSquare((x_old + 1) * (x_old +1)); + if (this->ult(square)) + return x_old; + else if (this->ule(nextSquare)) { + ap_private<_AP_W, _AP_S, _AP_N> midpoint((nextSquare - square).udiv(two)); + ap_private<_AP_W, _AP_S, _AP_N> offset(*this - square); + if (offset.ult(midpoint)) + return x_old; + else + return x_old + 1; + } else + assert(0 && "Error in ap_private<_AP_W, _AP_S, _AP_N>::sqrt computation"); + return x_old + 1; +} + +/// Implementation of Knuth's Algorithm D (Division of nonnegative integers) +/// from "Art of Computer Programming, Volume 2", section 4.3.1, p. 272. The +/// variables here have the same names as in the algorithm. Comments explain +/// the algorithm and any deviation from it. +static void KnuthDiv(uint32_t *u, uint32_t *v, uint32_t *q, uint32_t* r, + uint32_t m, uint32_t n) { + assert(u && "Must provide dividend"); + assert(v && "Must provide divisor"); + assert(q && "Must provide quotient"); + assert(u != v && u != q && v != q && "Must us different memory"); + assert(n>1 && "n must be > 1"); + + // Knuth uses the value b as the base of the number system. In our case b + // is 2^31 so we just set it to -1u. + uint64_t b = uint64_t(1) << 32; + + //DEBUG(cerr << "KnuthDiv: m=" << m << " n=" << n << '\n'); + //DEBUG(cerr << "KnuthDiv: original:"); + //DEBUG(for (int i = m+n; i >=0; i--) cerr << " " << std::setbase(16) << u[i]); + //DEBUG(cerr << " by"); + //DEBUG(for (int i = n; i >0; i--) cerr << " " << std::setbase(16) << v[i-1]); + //DEBUG(cerr << '\n'); + // D1. [Normalize.] Set d = b / (v[n-1] + 1) and multiply all the digits of + // u and v by d. Note that we have taken Knuth's advice here to use a power + // of 2 value for d such that d * v[n-1] >= b/2 (b is the base). A power of + // 2 allows us to shift instead of multiply and it is easy to determine the + // shift amount from the leading zeros. We are basically normalizing the u + // and v so that its high bits are shifted to the top of v's range without + // overflow. Note that this can require an extra word in u so that u must + // be of length m+n+1. + uint32_t shift = CountLeadingZeros_32(v[n-1]); + uint32_t v_carry = 0; + uint32_t u_carry = 0; + if (shift) { + for (uint32_t i = 0; i < m+n; ++i) { + uint32_t u_tmp = (u[i]) >> (32 - shift); + u[i] = ((u[i]) << (shift)) | u_carry; + u_carry = u_tmp; + } + for (uint32_t i = 0; i < n; ++i) { + uint32_t v_tmp = (v[i]) >> (32 - shift); + v[i] = ((v[i]) << (shift)) | v_carry; + v_carry = v_tmp; + } + } + u[m+n] = u_carry; + //DEBUG(cerr << "KnuthDiv: normal:"); + //DEBUG(for (int i = m+n; i >=0; i--) cerr << " " << std::setbase(16) << u[i]); + //DEBUG(cerr << " by"); + //DEBUG(for (int i = n; i >0; i--) cerr << " " << std::setbase(16) << v[i-1]); + //DEBUG(cerr << '\n'); + + // D2. [Initialize j.] Set j to m. This is the loop counter over the places. + int j = m; + do { + //DEBUG(cerr << "KnuthDiv: quotient digit #" << j << '\n'); + // D3. [Calculate q'.]. + // Set qp = (u[j+n]*b + u[j+n-1]) / v[n-1]. (qp=qprime=q') + // Set rp = (u[j+n]*b + u[j+n-1]) % v[n-1]. (rp=rprime=r') + // Now test if qp == b or qp*v[n-2] > b*rp + u[j+n-2]; if so, decrease + // qp by 1, inrease rp by v[n-1], and repeat this test if rp < b. The test + // on v[n-2] determines at high speed most of the cases in which the trial + // value qp is one too large, and it eliminates all cases where qp is two + // too large. + uint64_t dividend = ((uint64_t(u[j+n]) << 32) + u[j+n-1]); + //DEBUG(cerr << "KnuthDiv: dividend == " << dividend << '\n'); + uint64_t qp = dividend / v[n-1]; + uint64_t rp = dividend % v[n-1]; + if (qp == b || qp*v[n-2] > b*rp + u[j+n-2]) { + qp--; + rp += v[n-1]; + if (rp < b && (qp == b || qp*v[n-2] > b*rp + u[j+n-2])) + qp--; + } + //DEBUG(cerr << "KnuthDiv: qp == " << qp << ", rp == " << rp << '\n'); + + // D4. [Multiply and subtract.] Replace (u[j+n]u[j+n-1]...u[j]) with + // (u[j+n]u[j+n-1]..u[j]) - qp * (v[n-1]...v[1]v[0]). This computation + // consists of a simple multiplication by a one-place number, combined with + // a subtraction. + bool isNeg = false; + for (uint32_t i = 0; i < n; ++i) { + uint64_t u_tmp = uint64_t(u[j+i]) | ((uint64_t(u[j+i+1])) << 32); + uint64_t subtrahend = uint64_t(qp) * uint64_t(v[i]); + bool borrow = subtrahend > u_tmp; + /*DEBUG(cerr << "KnuthDiv: u_tmp == " << u_tmp + << ", subtrahend == " << subtrahend + << ", borrow = " << borrow << '\n');*/ + + uint64_t result = u_tmp - subtrahend; + uint32_t k = j + i; + u[k++] = (uint32_t)(result & (b-1)); // subtract low word + u[k++] = (uint32_t)((result) >> 32); // subtract high word + while (borrow && k <= m+n) { // deal with borrow to the left + borrow = u[k] == 0; + u[k]--; + k++; + } + isNeg |= borrow; + /*DEBUG(cerr << "KnuthDiv: u[j+i] == " << u[j+i] << ", u[j+i+1] == " << + u[j+i+1] << '\n');*/ + } + /*DEBUG(cerr << "KnuthDiv: after subtraction:"); + DEBUG(for (int i = m+n; i >=0; i--) cerr << " " << u[i]); + DEBUG(cerr << '\n');*/ + // The digits (u[j+n]...u[j]) should be kept positive; if the result of + // this step is actually negative, (u[j+n]...u[j]) should be left as the + // true value plus b**(n+1), namely as the b's complement of + // the true value, and a "borrow" to the left should be remembered. + // + if (isNeg) { + bool carry = true; // true because b's complement is "complement + 1" + for (uint32_t i = 0; i <= m+n; ++i) { + u[i] = ~u[i] + carry; // b's complement + carry = carry && u[i] == 0; + } + } + /*DEBUG(cerr << "KnuthDiv: after complement:"); + DEBUG(for (int i = m+n; i >=0; i--) cerr << " " << u[i]); + DEBUG(cerr << '\n');*/ + + // D5. [Test remainder.] Set q[j] = qp. If the result of step D4 was + // negative, go to step D6; otherwise go on to step D7. + q[j] = (uint32_t)qp; + if (isNeg) { + // D6. [Add back]. The probability that this step is necessary is very + // small, on the order of only 2/b. Make sure that test data accounts for + // this possibility. Decrease q[j] by 1 + q[j]--; + // and add (0v[n-1]...v[1]v[0]) to (u[j+n]u[j+n-1]...u[j+1]u[j]). + // A carry will occur to the left of u[j+n], and it should be ignored + // since it cancels with the borrow that occurred in D4. + bool carry = false; + for (uint32_t i = 0; i < n; i++) { + uint32_t limit = AESL_std::min(u[j+i],v[i]); + u[j+i] += v[i] + carry; + carry = u[j+i] < limit || (carry && u[j+i] == limit); + } + u[j+n] += carry; + } + /*DEBUG(cerr << "KnuthDiv: after correction:"); + DEBUG(for (int i = m+n; i >=0; i--) cerr <<" " << u[i]); + DEBUG(cerr << "\nKnuthDiv: digit result = " << q[j] << '\n');*/ + + // D7. [Loop on j.] Decrease j by one. Now if j >= 0, go back to D3. + } while (--j >= 0); + + /*DEBUG(cerr << "KnuthDiv: quotient:"); + DEBUG(for (int i = m; i >=0; i--) cerr <<" " << q[i]); + DEBUG(cerr << '\n');*/ + + // D8. [Unnormalize]. Now q[...] is the desired quotient, and the desired + // remainder may be obtained by dividing u[...] by d. If r is non-null we + // compute the remainder (urem uses this). + if (r) { + // The value d is expressed by the "shift" value above since we avoided + // multiplication by d by using a shift left. So, all we have to do is + // shift right here. In order to mak + if (shift) { + uint32_t carry = 0; + //DEBUG(cerr << "KnuthDiv: remainder:"); + for (int i = n-1; i >= 0; i--) { + r[i] = ((u[i]) >> (shift)) | carry; + carry = (u[i]) << (32 - shift); + //DEBUG(cerr << " " << r[i]); + } + } else { + for (int i = n-1; i >= 0; i--) { + r[i] = u[i]; + //DEBUG(cerr << " " << r[i]); + } + } + //DEBUG(cerr << '\n'); + } + //DEBUG(cerr << std::setbase(10) << '\n'); +} + +template +void divide(const ap_private<_AP_W, _AP_S, _AP_N>& LHS, uint32_t lhsWords, + const ap_private<_AP_W, _AP_S, _AP_N>& RHS, uint32_t rhsWords, + ap_private<_AP_W, _AP_S, _AP_N> *Quotient, ap_private<_AP_W, _AP_S, _AP_N> *Remainder) { + assert(lhsWords >= rhsWords && "Fractional result"); + enum {APINT_BITS_PER_WORD=64}; + // First, compose the values into an array of 32-bit words instead of + // 64-bit words. This is a necessity of both the "short division" algorithm + // and the the Knuth "classical algorithm" which requires there to be native + // operations for +, -, and * on an m bit value with an m*2 bit result. We + // can't use 64-bit operands here because we don't have native results of + // 128-bits. Furthremore, casting the 64-bit values to 32-bit values won't + // work on large-endian machines. + uint64_t mask = ~0ull >> (sizeof(uint32_t)*8); + uint32_t n = rhsWords * 2; + uint32_t m = (lhsWords * 2) - n; + + // Allocate space for the temporary values we need either on the stack, if + // it will fit, or on the heap if it won't. + uint32_t SPACE[128]; + uint32_t *__U = 0; + uint32_t *__V = 0; + uint32_t *__Q = 0; + uint32_t *__R = 0; + if ((Remainder?4:3)*n+2*m+1 <= 128) { + __U = &SPACE[0]; + __V = &SPACE[m+n+1]; + __Q = &SPACE[(m+n+1) + n]; + if (Remainder) + __R = &SPACE[(m+n+1) + n + (m+n)]; + } else { + __U = new uint32_t[m + n + 1]; + __V = new uint32_t[n]; + __Q = new uint32_t[m+n]; + if (Remainder) + __R = new uint32_t[n]; + } + + // Initialize the dividend + memset(__U, 0, (m+n+1)*sizeof(uint32_t)); + for (unsigned i = 0; i < lhsWords; ++i) { + uint64_t tmp = (LHS.getNumWords() == 1 ? LHS.VAL : LHS.pVal[i]); + __U[i * 2] = (uint32_t)(tmp & mask); + __U[i * 2 + 1] = (tmp) >> (sizeof(uint32_t)*8); + } + __U[m+n] = 0; // this extra word is for "spill" in the Knuth algorithm. + + // Initialize the divisor + memset(__V, 0, (n)*sizeof(uint32_t)); + for (unsigned i = 0; i < rhsWords; ++i) { + uint64_t tmp = (RHS.getNumWords() == 1 ? RHS.VAL : RHS.pVal[i]); + __V[i * 2] = (uint32_t)(tmp & mask); + __V[i * 2 + 1] = (tmp) >> (sizeof(uint32_t)*8); + } + + // initialize the quotient and remainder + memset(__Q, 0, (m+n) * sizeof(uint32_t)); + if (Remainder) + memset(__R, 0, n * sizeof(uint32_t)); + + // Now, adjust m and n for the Knuth division. n is the number of words in + // the divisor. m is the number of words by which the dividend exceeds the + // divisor (i.e. m+n is the length of the dividend). These sizes must not + // contain any zero words or the Knuth algorithm fails. + for (unsigned i = n; i > 0 && __V[i-1] == 0; i--) { + n--; + m++; + } + for (unsigned i = m+n; i > 0 && __U[i-1] == 0; i--) + m--; + + // If we're left with only a single word for the divisor, Knuth doesn't work + // so we implement the short division algorithm here. This is much simpler + // and faster because we are certain that we can divide a 64-bit quantity + // by a 32-bit quantity at hardware speed and short division is simply a + // series of such operations. This is just like doing short division but we + // are using base 2^32 instead of base 10. + assert(n != 0 && "Divide by zero?"); + if (n == 1) { + uint32_t divisor = __V[0]; + uint32_t remainder = 0; + for (int i = m+n-1; i >= 0; i--) { + uint64_t partial_dividend = (uint64_t(remainder)) << 32 | __U[i]; + if (partial_dividend == 0) { + __Q[i] = 0; + remainder = 0; + } else if (partial_dividend < divisor) { + __Q[i] = 0; + remainder = (uint32_t)partial_dividend; + } else if (partial_dividend == divisor) { + __Q[i] = 1; + remainder = 0; + } else { + __Q[i] = (uint32_t)(partial_dividend / divisor); + remainder = (uint32_t)(partial_dividend - (__Q[i] * divisor)); + } + } + if (__R) + __R[0] = remainder; + } else { + // Now we're ready to invoke the Knuth classical divide algorithm. In this + // case n > 1. + KnuthDiv(__U, __V, __Q, __R, m, n); + } + + // If the caller wants the quotient + if (Quotient) { + // Set up the Quotient value's memory. + if (Quotient->BitWidth != LHS.BitWidth) { + if (Quotient->isSingleWord()) + Quotient->VAL = 0; + } else + Quotient->clear(); + + // The quotient is in Q. Reconstitute the quotient into Quotient's low + // order words. + if (lhsWords == 1) { + uint64_t tmp = + uint64_t(__Q[0]) | ((uint64_t(__Q[1])) << (APINT_BITS_PER_WORD / 2)); + if (Quotient->isSingleWord()) + Quotient->VAL = tmp; + else + Quotient->pVal[0] = tmp; + } else { + assert(!Quotient->isSingleWord() && "Quotient ap_private not large enough"); + for (unsigned i = 0; i < lhsWords; ++i) + Quotient->pVal[i] = + uint64_t(__Q[i*2]) | ((uint64_t(__Q[i*2+1])) << (APINT_BITS_PER_WORD / 2)); + } + Quotient->clearUnusedBits(); + } + + // If the caller wants the remainder + if (Remainder) { + // Set up the Remainder value's memory. + if (Remainder->BitWidth != RHS.BitWidth) { + if (Remainder->isSingleWord()) + Remainder->VAL = 0; + } else + Remainder->clear(); + + // The remainder is in R. Reconstitute the remainder into Remainder's low + // order words. + if (rhsWords == 1) { + uint64_t tmp = + uint64_t(__R[0]) | ((uint64_t(__R[1])) << (APINT_BITS_PER_WORD / 2)); + if (Remainder->isSingleWord()) + Remainder->VAL = tmp; + else + Remainder->pVal[0] = tmp; + } else { + assert(!Remainder->isSingleWord() && "Remainder ap_private not large enough"); + for (unsigned i = 0; i < rhsWords; ++i) + Remainder->pVal[i] = + uint64_t(__R[i*2]) | ((uint64_t(__R[i*2+1])) << (APINT_BITS_PER_WORD / 2)); + } + Remainder->clearUnusedBits(); + } + + // Clean up the memory we allocated. + if (__U != &SPACE[0]) { + delete [] __U; + delete [] __V; + delete [] __Q; + delete [] __R; + } +} + + +template +void ap_private<_AP_W, _AP_S, _AP_N>::fromString(const char *str, uint32_t slen, uint8_t radix) { + enum { numbits=_AP_W}; + // Check our assumptions here + assert((radix == 10 || radix == 8 || radix == 16 || radix == 2) && + "Radix should be 2, 8, 10, or 16!"); + assert(str && "String is null?"); + bool isNeg = str[0] == '-'; + if (isNeg) + str++, slen--; + + //skip any leading zero + while(*str == '0' && *(str+1) != '\0') {str++; slen--;} + assert((slen <= numbits || radix != 2) && "Insufficient bit width"); + assert(((slen - 1)*3 <= numbits || radix != 8) && "Insufficient bit width"); + assert(((slen - 1)*4 <= numbits || radix != 16) && "Insufficient bit width"); + assert((((slen -1)*64)/22 <= numbits || radix != 10) && "Insufficient bit width"); + + memset(pVal, 0, _AP_N * sizeof(uint64_t)); + + // Figure out if we can shift instead of multiply + uint32_t shift = (radix == 16 ? 4 : radix == 8 ? 3 : radix == 2 ? 1 : 0); + + // Set up an ap_private for the digit to add outside the loop so we don't + // constantly construct/destruct it. + uint64_t bigVal[_AP_N]; + memset(bigVal, 0, _AP_N * sizeof(uint64_t)); + ap_private<_AP_W, _AP_S, _AP_N> apdigit(getBitWidth(), bigVal); + ap_private<_AP_W, _AP_S, _AP_N> apradix(radix); + + // Enter digit traversal loop + for (unsigned i = 0; i < slen; i++) { + // Get a digit + uint32_t digit = 0; + char cdigit = str[i]; + if (radix == 16) { +#define isxdigit(c) (((c) >= '0' && (c) <= '9') || ((c) >= 'a' && (c) <= 'f') || ((c) >= 'A' && (c) <= 'F')) +#define isdigit(c) ((c) >= '0' && (c) <= '9') + if (!isxdigit(cdigit)) + assert(0 && "Invalid hex digit in string"); + if (isdigit(cdigit)) + digit = cdigit - '0'; + else if (cdigit >= 'a') + digit = cdigit - 'a' + 10; + else if (cdigit >= 'A') + digit = cdigit - 'A' + 10; + else + assert(0 && "huh? we shouldn't get here"); + } else if (isdigit(cdigit)) { + digit = cdigit - '0'; + } else { + assert(0 && "Invalid character in digit string"); + } +#undef isxdigit +#undef isdigit + // Shift or multiply the value by the radix + if (shift) + *this <<= shift; + else + *this *= apradix; + + // Add in the digit we just interpreted + if (apdigit.isSingleWord()) + apdigit.VAL = digit; + else + apdigit.pVal[0] = digit; + *this += apdigit; + } + // If its negative, put it in two's complement form + if (isNeg) { + (*this)--; + this->flip(); + } + clearUnusedBits(); +} + +template +std::string ap_private<_AP_W, _AP_S, _AP_N>::toString(uint8_t radix, bool wantSigned) const { + assert((radix == 10 || radix == 8 || radix == 16 || radix == 2) && + "Radix should be 2, 8, 10, or 16!"); + static const char *digits[] = { + "0","1","2","3","4","5","6","7","8","9","A","B","C","D","E","F" + }; + std::string result; + uint32_t bits_used = getActiveBits(); + + if (radix != 10) { + // For the 2, 8 and 16 bit cases, we can just shift instead of divide + // because the number of bits per digit (1,3 and 4 respectively) divides + // equaly. We just shift until there value is zero. + + // First, check for a zero value and just short circuit the logic below. + if (*this == (uint64_t)(0)) + result = "0"; + else { + ap_private<_AP_W, false, _AP_N> tmp(*this); + size_t insert_at = 0; + if (wantSigned && isNegative()) { + // They want to print the signed version and it is a negative value + // Flip the bits and add one to turn it into the equivalent positive + // value and put a '-' in the result. + tmp.flip(); + tmp++; + tmp.clearUnusedBitsToZero(); + result = "-"; + insert_at = 1; + } + // Just shift tmp right for each digit width until it becomes zero + uint32_t shift = (radix == 16 ? 4 : (radix == 8 ? 3 : 1)); + uint64_t mask = radix - 1; + ap_private<_AP_W, false, _AP_N> zero(0); + while (tmp.ne(zero)) { + unsigned digit = (tmp.isSingleWord() ? tmp.VAL : tmp.pVal[0]) & mask; + result.insert(insert_at, digits[digit]); + tmp = tmp.lshr(shift); + } + } + return result; + } + + ap_private<_AP_W, false, _AP_N> tmp(*this); + ap_private<_AP_W, false, _AP_N> divisor(radix); + ap_private<_AP_W, false, _AP_N> zero(0); + size_t insert_at = 0; + if (wantSigned && isNegative()) { + // They want to print the signed version and it is a negative value + // Flip the bits and add one to turn it into the equivalent positive + // value and put a '-' in the result. + tmp.flip(); + tmp++; + tmp.clearUnusedBitsToZero(); + result = "-"; + insert_at = 1; + } + if (tmp == ap_private<_AP_W, false, _AP_N>(0)) + result = "0"; + else while (tmp.ne(zero)) { + ap_private<_AP_W, false, _AP_N> APdigit(0); + ap_private<_AP_W, false, _AP_N> tmp2(0); + divide(tmp, tmp.getNumWords(), divisor, divisor.getNumWords(), &tmp2, + &APdigit); + uint32_t digit = APdigit.getZExtValue(); + assert(digit < radix && "divide failed"); + result.insert(insert_at,digits[digit]); + tmp = tmp2; + } + + return result; +} + +// This implements a variety of operations on a representation of +// arbitrary precision, two's-complement, bignum integer values. + +/* Assumed by lowHalf, highHalf, partMSB and partLSB. A fairly safe + and unrestricting assumption. */ + +/* Some handy functions local to this file. */ + +template +void divide(const ap_private<_AP_W, _AP_S, _AP_N>& LHS, uint32_t lhsWords, + uint64_t RHS, + ap_private<_AP_W, _AP_S, _AP_N> *Quotient, ap_private<_AP_W, _AP_S, _AP_N> *Remainder) { + uint32_t rhsWords=1; + assert(lhsWords >= rhsWords && "Fractional result"); + enum {APINT_BITS_PER_WORD=64}; + // First, compose the values into an array of 32-bit words instead of + // 64-bit words. This is a necessity of both the "short division" algorithm + // and the the Knuth "classical algorithm" which requires there to be native + // operations for +, -, and * on an m bit value with an m*2 bit result. We + // can't use 64-bit operands here because we don't have native results of + // 128-bits. Furthremore, casting the 64-bit values to 32-bit values won't + // work on large-endian machines. + uint64_t mask = ~0ull >> (sizeof(uint32_t)*8); + uint32_t n = 2; + uint32_t m = (lhsWords * 2) - n; + + // Allocate space for the temporary values we need either on the stack, if + // it will fit, or on the heap if it won't. + uint32_t SPACE[128]; + uint32_t *__U = 0; + uint32_t *__V = 0; + uint32_t *__Q = 0; + uint32_t *__R = 0; + if ((Remainder?4:3)*n+2*m+1 <= 128) { + __U = &SPACE[0]; + __V = &SPACE[m+n+1]; + __Q = &SPACE[(m+n+1) + n]; + if (Remainder) + __R = &SPACE[(m+n+1) + n + (m+n)]; + } else { + __U = new uint32_t[m + n + 1]; + __V = new uint32_t[n]; + __Q = new uint32_t[m+n]; + if (Remainder) + __R = new uint32_t[n]; + } + + // Initialize the dividend + memset(__U, 0, (m+n+1)*sizeof(uint32_t)); + for (unsigned i = 0; i < lhsWords; ++i) { + uint64_t tmp = (LHS.getNumWords() == 1 ? LHS.VAL : LHS.pVal[i]); + __U[i * 2] = tmp & mask; + __U[i * 2 + 1] = (tmp) >> (sizeof(uint32_t)*8); + } + __U[m+n] = 0; // this extra word is for "spill" in the Knuth algorithm. + + // Initialize the divisor + memset(__V, 0, (n)*sizeof(uint32_t)); + __V[0] = RHS & mask; + __V[1] = (RHS) >> (sizeof(uint32_t)*8); + + // initialize the quotient and remainder + memset(__Q, 0, (m+n) * sizeof(uint32_t)); + if (Remainder) + memset(__R, 0, n * sizeof(uint32_t)); + + // Now, adjust m and n for the Knuth division. n is the number of words in + // the divisor. m is the number of words by which the dividend exceeds the + // divisor (i.e. m+n is the length of the dividend). These sizes must not + // contain any zero words or the Knuth algorithm fails. + for (unsigned i = n; i > 0 && __V[i-1] == 0; i--) { + n--; + m++; + } + for (unsigned i = m+n; i > 0 && __U[i-1] == 0; i--) + m--; + + // If we're left with only a single word for the divisor, Knuth doesn't work + // so we implement the short division algorithm here. This is much simpler + // and faster because we are certain that we can divide a 64-bit quantity + // by a 32-bit quantity at hardware speed and short division is simply a + // series of such operations. This is just like doing short division but we + // are using base 2^32 instead of base 10. + assert(n != 0 && "Divide by zero?"); + if (n == 1) { + uint32_t divisor = __V[0]; + uint32_t remainder = 0; + for (int i = m+n-1; i >= 0; i--) { + uint64_t partial_dividend = (uint64_t(remainder)) << 32 | __U[i]; + if (partial_dividend == 0) { + __Q[i] = 0; + remainder = 0; + } else if (partial_dividend < divisor) { + __Q[i] = 0; + remainder = partial_dividend; + } else if (partial_dividend == divisor) { + __Q[i] = 1; + remainder = 0; + } else { + __Q[i] = partial_dividend / divisor; + remainder = partial_dividend - (__Q[i] * divisor); + } + } + if (__R) + __R[0] = remainder; + } else { + // Now we're ready to invoke the Knuth classical divide algorithm. In this + // case n > 1. + KnuthDiv(__U, __V, __Q, __R, m, n); + } + + // If the caller wants the quotient + if (Quotient) { + // Set up the Quotient value's memory. + if (Quotient->BitWidth != LHS.BitWidth) { + if (Quotient->isSingleWord()) + Quotient->VAL = 0; + else + delete [] Quotient->pVal; + } else + Quotient->clear(); + + // The quotient is in Q. Reconstitute the quotient into Quotient's low + // order words. + if (lhsWords == 1) { + uint64_t tmp = + uint64_t(__Q[0]) | ((uint64_t(__Q[1])) << (APINT_BITS_PER_WORD / 2)); + if (Quotient->isSingleWord()) + Quotient->VAL = tmp; + else + Quotient->pVal[0] = tmp; + } else { + assert(!Quotient->isSingleWord() && "Quotient ap_private not large enough"); + for (unsigned i = 0; i < lhsWords; ++i) + Quotient->pVal[i] = + uint64_t(__Q[i*2]) | ((uint64_t(__Q[i*2+1])) << (APINT_BITS_PER_WORD / 2)); + } + Quotient->clearUnusedBits(); + } + + // If the caller wants the remainder + if (Remainder) { + // Set up the Remainder value's memory. + if (Remainder->BitWidth != 64 /* RHS.BitWidth */) { + if (Remainder->isSingleWord()) + Remainder->VAL = 0; + } else + Remainder->clear(); + + // The remainder is in __R. Reconstitute the remainder into Remainder's low + // order words. + if (rhsWords == 1) { + uint64_t tmp = + uint64_t(__R[0]) | ((uint64_t(__R[1])) << (APINT_BITS_PER_WORD / 2)); + if (Remainder->isSingleWord()) + Remainder->VAL = tmp; + else + Remainder->pVal[0] = tmp; + } else { + assert(!Remainder->isSingleWord() && "Remainder ap_private not large enough"); + for (unsigned i = 0; i < rhsWords; ++i) + Remainder->pVal[i] = + uint64_t(__R[i*2]) | ((uint64_t(__R[i*2+1])) << (APINT_BITS_PER_WORD / 2)); + } + Remainder->clearUnusedBits(); + } + + // Clean up the memory we allocated. + if (__U != &SPACE[0]) { + delete [] __U; + delete [] __V; + delete [] __Q; + delete [] __R; + } +} + +//When bitwidth < 64 +template class ap_private <_AP_W, _AP_S, 1> { +#ifdef _MSC_VER +#pragma warning( disable : 4521 4522 ) +#endif +public: + typedef typename retval<_AP_S>::Type ValType; + template + struct RType { + enum { + _AP_N =1, + mult_w = _AP_W+_AP_W2, + mult_s = _AP_S||_AP_S2, //?? why + plus_w = AP_MAX(_AP_W+(_AP_S2&&!_AP_S),_AP_W2+(_AP_S&&!_AP_S2))+1, //shouldn't it be AP_MAX(_AP_W,_AP_W2)+!(_AP_S^_AP_S2)+1 ???? + plus_s = _AP_S||_AP_S2, + minus_w = AP_MAX(_AP_W+(_AP_S2&&!_AP_S),_AP_W2+(_AP_S&&!_AP_S2))+1, + minus_s = true, + div_w = _AP_W+_AP_S2, + div_s = _AP_S||_AP_S2, + mod_w = AP_MIN(_AP_W,_AP_W2+(!_AP_S2&&_AP_S)), + mod_s = _AP_S, + logic_w = AP_MAX(_AP_W+(_AP_S2&&!_AP_S),_AP_W2+(_AP_S&&!_AP_S2)), + logic_s = _AP_S||_AP_S2 + }; + typedef ap_private mult; + typedef ap_private plus; + typedef ap_private minus; + typedef ap_private logic; + typedef ap_private div; + typedef ap_private mod; + typedef ap_private<_AP_W, _AP_S> arg1; + typedef bool reduce; + }; + enum { APINT_BITS_PER_WORD = 64}; + enum { excess_bits = (_AP_W%APINT_BITS_PER_WORD) ? APINT_BITS_PER_WORD -(_AP_W%APINT_BITS_PER_WORD) : 0}; + static const uint64_t mask = ((uint64_t)~0ULL >> (excess_bits)); + static const uint64_t not_mask = ~mask; + static const uint64_t sign_bit_mask = 1ULL << (APINT_BITS_PER_WORD-1); + template struct sign_ext_mask { static const uint64_t mask=~0ULL<<_AP_W1;}; + + enum { BitWidth=_AP_W}; + uint64_t VAL; ///< Used to store the <= 64 bits integer value. + const uint64_t *const pVal; + + INLINE uint32_t getBitWidth() const { + return BitWidth; + } + + template + ap_private<_AP_W, _AP_S, 1>& operator=(const ap_private<_AP_W1, _AP_S1, _AP_N1>& RHS) { + VAL = RHS.pVal[0]; + clearUnusedBits(); + return *this; + } + + template + ap_private<_AP_W, _AP_S, 1>& operator=(const volatile ap_private<_AP_W1, _AP_S1, _AP_N1>& RHS) { + VAL = RHS.pVal[0]; + clearUnusedBits(); + return *this; + } + + template + ap_private<_AP_W, _AP_S, 1>& operator=(const ap_private<_AP_W1, _AP_S1, 1>& RHS) { + VAL = RHS.VAL; + clearUnusedBits(); + return *this; + } + + template + ap_private<_AP_W, _AP_S, 1>& operator=(const volatile ap_private<_AP_W1, _AP_S1, 1>& RHS) { + VAL = RHS.VAL; + clearUnusedBits(); + return *this; + } + + volatile ap_private& operator=(const ap_private& RHS) volatile { + // Don't do anything for X = X + VAL = RHS.VAL; // No need to check because no harm done by copying. + return *this; + } + ap_private& operator=(const ap_private& RHS) { + // Don't do anything for X = X + VAL = RHS.VAL; // No need to check because no harm done by copying. + return *this; + } + + volatile ap_private& operator=(const volatile ap_private& RHS) volatile { + // Don't do anything for X = X + VAL = RHS.VAL; // No need to check because no harm done by copying. + return *this; + } + ap_private& operator=(const volatile ap_private& RHS) { + // Don't do anything for X = X + VAL = RHS.VAL; // No need to check because no harm done by copying. + return *this; + } + + template + INLINE ap_private& operator = (const ap_range_ref<_AP_W2, _AP_S2>& op2) { + *this = ap_private<_AP_W2, false>(op2); + return *this; + } + + explicit INLINE ap_private(uint64_t* val) : VAL(val[0]), pVal(&VAL){ + clearUnusedBits(); + } + + INLINE bool isSingleWord() const { return true; } + + INLINE void fromString(const char *strStart, uint32_t slen, + uint8_t radix, int offset=0) { + // Check our assumptions here + assert((radix == 10 || radix == 8 || radix == 16 || radix == 2) && + "Radix should be 2, 8, 10, or 16!"); + assert(strStart && "String is null?"); + strStart+=offset; + switch(radix) { + case 2: + // sscanf(strStart,"%b",&VAL); + VAL = *strStart =='1' ? ~0ULL : 0; + for (;*strStart; ++strStart) { + assert((*strStart=='0'|| *strStart=='1')&&("Wrong binary number") ); + VAL <<=1; + VAL |= (*strStart-'0'); + } + break; + case 8: +#if __WIN32__ + sscanf(strStart,"%I64o",&VAL); +#else + +#if defined __x86_64__ + sscanf(strStart,"%lo",&VAL); +#else + sscanf(strStart,"%llo",&VAL); +#endif + +#endif + break; + case 10: +#if __WIN32__ + sscanf(strStart,"%I64u",&VAL); +#else + +#if defined __x86_64__ + sscanf(strStart,"%lu",&VAL); +#else + sscanf(strStart,"%llu",&VAL); +#endif + +#endif + break; + case 16: +#if __WIN32__ + sscanf(strStart,"%I64x",&VAL); +#else + +#if defined __x86_64__ + sscanf(strStart,"%lx",&VAL); +#else + sscanf(strStart,"%llx",&VAL); +#endif + +#endif + break; + default: + assert(true && "Unknown radix"); + // error + } + clearUnusedBits(); + } + + INLINE ap_private() : pVal(&VAL){VAL = 0ULL;} + +#define CTOR(TYPE) \ + INLINE ap_private(TYPE v) : VAL((uint64_t)v), pVal(&VAL) { \ + clearUnusedBits(); \ + } + CTOR(int) + CTOR(bool) + CTOR(signed char) + CTOR(unsigned char) + CTOR(short) + CTOR(unsigned short) + CTOR(unsigned int) + CTOR(long) + CTOR(unsigned long) + CTOR(unsigned long long) + CTOR(long long) + CTOR(float) + CTOR(double) +#undef CTOR + ap_private(uint32_t numWords, const uint64_t bigVal[]): VAL(bigVal[0]), pVal(&VAL) {clearUnusedBits();} + + ap_private(const std::string& val, uint8_t radix=2, int base=0, int offset=0): VAL(0), pVal(&VAL) { + assert(!val.empty() && "String empty?"); + fromString(val.c_str()+base, val.size()-base, radix); + } + + ap_private(const char strStart[], uint32_t slen, uint8_t radix, int base=0, int offset=0) : VAL(0), pVal(&VAL) { + fromString(strStart+base, slen-base, radix, offset); + } + + ap_private(const ap_private& that) : VAL(that.VAL), pVal(&VAL) { + clearUnusedBits(); + } + + template + ap_private(const ap_private<_AP_W1, _AP_S1, 1>& that) : VAL(that.VAL), pVal(&VAL) { + clearUnusedBits(); + } + + template + ap_private(const ap_private<_AP_W1, _AP_S1, _AP_N1>& that) : VAL(that.pVal[0]), pVal(&VAL) { + clearUnusedBits(); + } + + template + ap_private(const volatile ap_private<_AP_W1, _AP_S1, _AP_N1>& that) : VAL(that.pVal[0]), pVal(&VAL) { + clearUnusedBits(); + } + +#if 0 +template + explicit ap_private(const ap_private<_AP_W1, true, 1+_AP_W1/64>& that) + : VAL((_AP_W1>_AP_W) ? that.VAL & mask : ((1ULL<<(_AP_W1-1)&that.pVal[0]) ? sign_ext_mask<_AP_W1>::mask | that.VAL : that.pVal[0])), pVal(&VAL) {} + +template + explicit ap_private(const ap_private<_AP_W1, false, (_AP_W1+63)/64>& that) + : VAL(that.VAL & mask), pVal(&VAL) {} +#endif + + explicit ap_private(const char* val) : pVal(&VAL) { + std::string str(val); + uint32_t strLen = str.length(); + const char *strp = str.c_str(); + uint32_t offset = 0; + uint32_t base = 0; + bool neg = false; + uint32_t radix = 10; + ap_parse_sign(strp, base, neg); + ap_parse_prefix(strp + base, offset, radix); + + if ((radix != 10 && neg) || + (strLen - base - offset <= 0) || + InvalidDigit(strp, strLen, base + offset, radix)) { + fprintf(stderr, "invalid character string %s !\n", val); + assert(0); + } + + ap_private<_AP_W, _AP_S> ap_private_val(str.c_str(), strLen, radix, base, offset); + if (neg) + ap_private_val = -ap_private_val; + operator = (ap_private_val); + } + + ap_private(const char* val, signed char rd): pVal(&VAL) { + std::string str(val); + uint32_t strLen = str.length(); + const char *strp = str.c_str(); + uint32_t offset = 0; + uint32_t base = 0; + uint32_t radix = rd; + bool neg = false; + ap_parse_sign(strp, base, neg); + ap_parse_prefix(strp + base, offset, radix); + + if ((radix != 10 && neg) || + (strLen - base - offset <= 0) || + InvalidDigit(strp, strLen, base + offset, radix)) { + fprintf(stderr, "invalid character string %s !\n", val); + assert(0); + } + + uint32_t bitsNeeded = ap_private<_AP_W, _AP_S>::getBitsNeeded(strp, strLen, radix); + ap_private<_AP_W, _AP_S> ap_private_val(strp , strLen, radix, base, offset); + //ap_private<_AP_W, _AP_S> ap_private_val(bitsNeeded, strp , strLen, radix, base, offset); + if (strp[0] == '-') + ap_private_val = -ap_private_val; + operator = (ap_private_val); + } + + INLINE bool isNegative() const { + static const uint64_t sign_mask = 1ULL << (_AP_W-1); + return _AP_S && (sign_mask & VAL); + } + + INLINE bool isPositive() const { + return !isNegative(); + } + + INLINE bool isStrictlyPositive() const { + return !isNegative() && VAL!=0; + } + + INLINE bool isAllOnesValue() const { + return (mask & VAL) == mask; + } + + template + INLINE bool operator==(const ap_private<_AP_W1, _AP_S1, 1>& RHS) const { + return (VAL == RHS.VAL); + } + + INLINE bool operator==(const ap_private<_AP_W, _AP_S>& RHS) const { return VAL == RHS.VAL; } + INLINE bool operator==(const ap_private<_AP_W, !_AP_S>& RHS) const { return getVal() == RHS.getVal(); } + INLINE bool operator==(uint64_t Val) const { return (VAL == Val); } + INLINE bool operator!=(uint64_t Val) const { return (VAL != Val); } + INLINE bool operator!=(const ap_private<_AP_W, _AP_S>& RHS) const { return VAL != RHS.VAL; } + INLINE bool operator!=(const ap_private<_AP_W, !_AP_S>& RHS) const { return getVal() != RHS.getVal(); } + const ap_private operator++() { ++VAL; clearUnusedBits(); return *this; } + const ap_private operator--(int) { + ap_private orig(*this); + --VAL; clearUnusedBits(); + return orig; + } + const ap_private operator--() { --VAL; clearUnusedBits(); return *this;} + INLINE bool operator !() const { return !VAL;} + + const ap_private operator++(int) { + ap_private orig(*this); + VAL++; clearUnusedBits(); + return orig; + } + + const ap_private operator~() {return ap_private(~VAL);} + INLINE typename RType<1,false>::minus operator-() const { + return ap_private<1,false>(0) - (*this); + } + + INLINE std::string toString(uint8_t radix, bool wantSigned) const ; + INLINE std::string toStringUnsigned(uint8_t radix = 10) const { + return toString(radix, false); + } + INLINE std::string toStringSigned(uint8_t radix = 10) const { + return toString(radix, true); + } + INLINE void clear() { + VAL=0; + } + INLINE ap_private& clear(uint32_t bitPosition) { VAL &= ~(1ULL<<(bitPosition)); clearUnusedBits(); return *this;} + + INLINE ap_private ashr(uint32_t shiftAmt) const { + enum {excess_bits = APINT_BITS_PER_WORD - BitWidth}; + if (_AP_S) + return ap_private((shiftAmt == BitWidth) ? 0 : ((int64_t)VAL) >> (shiftAmt)); + else + return ap_private((shiftAmt == BitWidth) ? 0 : (VAL) >> (shiftAmt)); + } + + INLINE ap_private lshr(uint32_t shiftAmt) const { + return ap_private((shiftAmt == BitWidth) ? ap_private(0) : ap_private((VAL&mask) >> (shiftAmt))); + } + + INLINE ap_private shl(uint32_t shiftAmt) const { + if (shiftAmt > BitWidth) { + if (!isNegative()) + return ap_private(0); + else return ap_private(-1); + } + if (shiftAmt == BitWidth) return ap_private(0); + else return ap_private((VAL) << (shiftAmt)); + //return ap_private((shiftAmt == BitWidth) ? ap_private(0ULL) : ap_private(VAL << shiftAmt)); + } + + INLINE int64_t getSExtValue() const { + return VAL; + } + + INLINE uint64_t getZExtValue() const { + return VAL & mask; + } + + template + INLINE ap_private(const ap_range_ref<_AP_W2,_AP_S2>& ref) : pVal(&VAL) { + *this=ref.get(); + } + + template + INLINE ap_private(const ap_bit_ref<_AP_W2,_AP_S2>& ref) : pVal(&VAL) { + *this = ((uint64_t)(bool)ref); + } + + template + INLINE ap_private(const ap_concat_ref<_AP_W2, _AP_T2,_AP_W3, _AP_T3>& ref) : pVal(&VAL) { + *this=ref.get(); + } + + template + INLINE ap_private(const af_range_ref<_AP_W2, _AP_I2, _AP_S2, + _AP_Q2, _AP_O2, _AP_N2> &val) : pVal(&VAL) { + *this = ((val.operator ap_private<_AP_W2, false> ())); + } + + template + INLINE ap_private(const af_bit_ref<_AP_W2, _AP_I2, _AP_S2, + _AP_Q2, _AP_O2, _AP_N2> &val) : pVal(&VAL) { + *this = (uint64_t)(bool)val; + } + + INLINE void write(const ap_private<_AP_W, _AP_S>& op2) volatile { + *this = (op2); + } + + //Explicit conversions to C interger types + //----------------------------------------------------------- + ValType getVal() const { + return VAL; + } + operator ValType () const { + return getVal(); + } + INLINE int to_int() const { + // ap_private<64 /* _AP_W */, _AP_S> res(V); + return (int) getVal(); + } + + INLINE unsigned to_uint() const { + return (unsigned) getVal(); + } + + INLINE long to_long() const { + return (long) getVal(); + } + + INLINE unsigned long to_ulong() const { + return (unsigned long) getVal(); + } + + INLINE ap_slong to_int64() const { + return (ap_slong) getVal(); + } + + INLINE ap_ulong to_uint64() const { + return (ap_ulong) getVal(); + } + + INLINE double to_double() const { + if (isNegative()) + return roundToDouble(true); + else + return roundToDouble(false); + } + + INLINE bool isMinValue() const { return VAL == 0;} + template INLINE ap_private& operator&=(const ap_private<_AP_W1, _AP_S1>& RHS) { + VAL = VAL&RHS.pVal[0]; + clearUnusedBits(); + return *this; + } + + template INLINE ap_private& operator|=(const ap_private<_AP_W1, _AP_S1>& RHS) { + VAL = VAL|RHS.pVal[0]; + clearUnusedBits(); + return *this; + } + + template INLINE ap_private& operator^=(const ap_private<_AP_W1, _AP_S1>& RHS){ + VAL = VAL^RHS.pVal[0]; + clearUnusedBits(); + return *this; + } + + template INLINE ap_private& operator*=(const ap_private<_AP_W1, _AP_S1>& RHS){ + VAL = VAL*RHS.pVal[0]; + clearUnusedBits(); + return *this; + } + + template INLINE ap_private& operator+=(const ap_private<_AP_W1, _AP_S1>& RHS){ + VAL = VAL+RHS.pVal[0]; + clearUnusedBits(); + return *this; + } + + template INLINE ap_private& operator-=(const ap_private<_AP_W1, _AP_S1>& RHS){ + VAL = VAL-RHS.pVal[0]; + clearUnusedBits(); + return *this; + } + INLINE const ap_private& operator<<=(uint32_t shiftAmt) { VAL<<=shiftAmt; clearUnusedBits(); return *this; } + + template INLINE typename RType<_AP_W1, _AP_S1>::logic operator&(const ap_private<_AP_W1, _AP_S1>& RHS) const { + if (RType<_AP_W1, _AP_S1>::logic_w <= 64) { + typename RType<_AP_W1, _AP_S1>::logic Ret(VAL & RHS.VAL); + return Ret; + } else { + typename RType<_AP_W1, _AP_S1>::logic Ret = *this; + return Ret & RHS; + } + } + + template INLINE typename RType<_AP_W1, _AP_S1>::logic operator^(const ap_private<_AP_W1, _AP_S1>& RHS) const { + if (RType<_AP_W1, _AP_S1>::logic_w <= 64) { + typename RType<_AP_W1, _AP_S1>::logic Ret(VAL ^ RHS.VAL); + return Ret; + } else { + typename RType<_AP_W1, _AP_S1>::logic Ret = *this; + return Ret ^ RHS; + } + } + + template INLINE typename RType<_AP_W1, _AP_S1>::logic operator|(const ap_private<_AP_W1, _AP_S1>& RHS) const { + if (RType<_AP_W1, _AP_S1>::logic_w <= 64) { + typename RType<_AP_W1, _AP_S1>::logic Ret(VAL | RHS.VAL); + return Ret; + } else { + typename RType<_AP_W1, _AP_S1>::logic Ret = *this; + return Ret | RHS; + } + } + + INLINE ap_private<_AP_W, _AP_S> And(const ap_private<_AP_W, _AP_S>& RHS) const { + return ap_private<_AP_W, _AP_S>(VAL & RHS.VAL); + } + + INLINE ap_private<_AP_W, _AP_S> Or(const ap_private<_AP_W, _AP_S>& RHS) const { + return ap_private<_AP_W, _AP_S>(VAL | RHS.VAL); + } + + INLINE ap_private<_AP_W, _AP_S> Xor(const ap_private<_AP_W, _AP_S>& RHS) const { + return ap_private<_AP_W, _AP_S>(VAL ^ RHS.VAL); + } +#if 1 + template + INLINE typename RType<_AP_W1, _AP_S1>::mult operator*(const ap_private<_AP_W1, _AP_S1>& RHS) const { + if (RType<_AP_W1, _AP_S1>::mult_w <= 64) { + typename RType<_AP_W1, _AP_S1>::mult Result(VAL * RHS.VAL); + return Result; + } else { + typename RType<_AP_W1, _AP_S1>::mult Result = typename RType<_AP_W1, _AP_S1>::mult(*this); + Result *= RHS; + return Result; + } + } +#endif + INLINE ap_private<_AP_W, _AP_S> Mul(const ap_private<_AP_W, _AP_S>& RHS) const { + return ap_private<_AP_W, _AP_S>(VAL * RHS.VAL); + } + + INLINE ap_private<_AP_W, _AP_S> Add(const ap_private<_AP_W, _AP_S>& RHS) const { + return ap_private<_AP_W, _AP_S>(VAL + RHS.VAL); + } + + INLINE ap_private<_AP_W, _AP_S> Sub(const ap_private<_AP_W, _AP_S>& RHS) const { + return ap_private<_AP_W, _AP_S>(VAL - RHS.VAL); + } + +#if 1 + INLINE ap_private& operator&=(uint64_t RHS) { VAL &= RHS; clearUnusedBits(); return *this;} + INLINE ap_private& operator|=(uint64_t RHS) { VAL |= RHS; clearUnusedBits(); return *this;} + INLINE ap_private& operator^=(uint64_t RHS){ VAL ^= RHS; clearUnusedBits(); return *this;} + INLINE ap_private& operator*=(uint64_t RHS){ VAL *= RHS; clearUnusedBits(); return *this; } + INLINE ap_private& operator+=(uint64_t RHS){ VAL += RHS; clearUnusedBits(); return *this;} + INLINE ap_private& operator-=(uint64_t RHS){ VAL -= RHS; clearUnusedBits(); return *this; } + INLINE ap_private operator&(uint64_t RHS) const { return ap_private(VAL & RHS); } + INLINE ap_private operator|(uint64_t RHS) const { return ap_private(VAL | RHS); } + INLINE ap_private operator^(uint64_t RHS) const { return ap_private(VAL ^ RHS); } + INLINE ap_private operator*(uint64_t RHS) const { return ap_private(VAL * RHS); } + INLINE ap_private operator/(uint64_t RHS) const { return ap_private(VAL / RHS); } + INLINE ap_private operator+(uint64_t RHS) const { return ap_private(VAL + RHS); } + INLINE ap_private operator-(uint64_t RHS) const { return ap_private(VAL - RHS); } +#endif + INLINE bool isMinSignedValue() const { + static const uint64_t min_mask = ~(~0ULL << (_AP_W-1)); + return BitWidth == 1 ? VAL == 1 : + (ap_private_ops::isNegative<_AP_W>(*this) && ((min_mask & VAL)==0)); + } + +#if 1 + + template INLINE + typename RType<_AP_W1,_AP_S1>::plus operator+(const ap_private<_AP_W1, _AP_S1>& RHS) const { + if (RType<_AP_W1,_AP_S1>::plus_w <=64) + return typename RType<_AP_W1,_AP_S1>::plus(RType<_AP_W1,_AP_S1>::plus_s ? int64_t(VAL+RHS.VAL):uint64_t(VAL+RHS.VAL)); + typename RType<_AP_W1,_AP_S1>::plus Result=RHS; + Result += VAL; + return Result; + } + + template INLINE + typename RType<_AP_W1,_AP_S1>::minus operator-(const ap_private<_AP_W1, _AP_S1>& RHS) const { + if (RType<_AP_W1,_AP_S1>::minus_w <=64) + return typename RType<_AP_W1,_AP_S1>::minus(int64_t(VAL-RHS.VAL)); + typename RType<_AP_W1,_AP_S1>::minus Result=*this; + Result -= RHS; + return Result; + } +#endif // #if 1 + + INLINE ap_private& flip() { + VAL = (~0ULL^VAL)&mask; + clearUnusedBits(); + return *this; + } + + uint32_t countPopulation() const { return CountPopulation_64(VAL);} + uint32_t countLeadingZeros() const { + int remainder = BitWidth % APINT_BITS_PER_WORD; + int excessBits = (APINT_BITS_PER_WORD - remainder) % APINT_BITS_PER_WORD; + //enum { remainder = BitWidth % APINT_BITS_PER_WORD, excessBits = APINT_BITS_PER_WORD - remainder}; + uint32_t Count = CountLeadingZeros_64(VAL); + if (Count) + Count-=excessBits; + return AESL_std::min(Count, (uint32_t)_AP_W); + } + + /// HiBits - This function returns the high "numBits" bits of this ap_private. + ap_private<_AP_W, _AP_S, 1> getHiBits(uint32_t numBits) const { + ap_private<_AP_W, _AP_S, 1> ret(*this); + ret = (ret)>>(BitWidth - numBits); + return ret; + } + + /// LoBits - This function returns the low "numBits" bits of this ap_private. + ap_private<_AP_W, _AP_S, 1> getLoBits(uint32_t numBits) const { + ap_private<_AP_W, _AP_S, 1> ret((VAL) << (BitWidth - numBits)); + ret = (ret)>>(BitWidth - numBits); + return ret; + //return ap_private(numBits, (VAL << (BitWidth - numBits))>> (BitWidth - numBits)); + } + + ap_private<_AP_W, _AP_S,1>& set(uint32_t bitPosition) { + VAL |= (1ULL << (bitPosition)); + clearUnusedBits(); + return *this; // clearUnusedBits(); + } + + void set() { + VAL = ~0ULL; + clearUnusedBits(); + } + + template + INLINE void set(const ap_private<_AP_W3, false> & val) { + operator = (ap_private<_AP_W3, _AP_S>(val)); + } + + INLINE void set(const ap_private & val) { + operator = (val); + } + + bool operator[](uint32_t bitPosition) const { + return (((1ULL << (bitPosition)) & VAL) != 0); + } + + INLINE void clearUnusedBits(void) { + enum { excess_bits = (_AP_W%APINT_BITS_PER_WORD) ? APINT_BITS_PER_WORD -_AP_W%APINT_BITS_PER_WORD : 0}; + VAL = _AP_S ? ((((int64_t)VAL)<<(excess_bits))>> (excess_bits)) : (excess_bits ? ((VAL)<<(excess_bits))>>(excess_bits) : VAL); + } + + INLINE void clearUnusedBitsToZero(void) { + enum { excess_bits = (_AP_W%APINT_BITS_PER_WORD) ? APINT_BITS_PER_WORD -_AP_W%APINT_BITS_PER_WORD : 0}; + static uint64_t mask = ~0ULL >> (excess_bits); + VAL &= mask; + } + + template + INLINE ap_private<_AP_W, _AP_S||_AP_S1> udiv(const ap_private<_AP_W, _AP_S1>& RHS) const { + return ap_private<_AP_W, _AP_S||_AP_S1>(VAL / RHS.VAL); + } + + INLINE ap_private udiv(uint64_t RHS) const { + return ap_private(VAL / RHS); + } + + /// Signed divide this ap_private by ap_private RHS. + /// @brief Signed division function for ap_private. + template + INLINE ap_private<_AP_W, _AP_S||_AP_S1> sdiv(const ap_private<_AP_W, _AP_S1> & RHS) const { + if (isNegative()) + if (RHS.isNegative()) + return (-(*this)).udiv(-RHS); + else + return -((-(*this)).udiv(RHS)); + else if (RHS.isNegative()) + return -(this->udiv(-RHS)); + return this->udiv(RHS); + } + + /// Signed divide this ap_private by ap_private RHS. + /// @brief Signed division function for ap_private. + INLINE ap_private sdiv(int64_t RHS) const { + if (isNegative()) + if (RHS<0) + return (-(*this)).udiv(-RHS); + else + return -((-(*this)).udiv(RHS)); + else if (RHS<0) + return -(this->udiv(-RHS)); + return this->udiv(RHS); + } + + template + INLINE ap_private urem(const ap_private<_AP_W, _AP_S2>& RHS) const { + assert(RHS.VAL != 0 && "Divide by 0"); + return ap_private(VAL%RHS.VAL); + } + + INLINE ap_private urem(uint64_t RHS) const { + assert(RHS != 0 && "Divide by 0"); + return ap_private(VAL%RHS); + } + + /// Signed remainder operation on ap_private. + /// @brief Function for signed remainder operation. + template + INLINE ap_private srem(const ap_private<_AP_W, _AP_S2>& RHS) const { + if (isNegative()) { + ap_private lhs = -(*this); + if (RHS.isNegative()) { + ap_private rhs = -RHS; + return -(lhs.urem(rhs)); + } else + return -(lhs.urem(RHS)); + } else if (RHS.isNegative()) { + ap_private rhs = -RHS; + return this->urem(rhs); + } + return this->urem(RHS); + } + + /// Signed remainder operation on ap_private. + /// @brief Function for signed remainder operation. + INLINE ap_private srem(int64_t RHS) const { + if (isNegative()) + if (RHS<0) + return -((-(*this)).urem(-RHS)); + else + return -((-(*this)).urem(RHS)); + else if (RHS<0) + return this->urem(-RHS); + return this->urem(RHS); + } + + INLINE static void udivrem(const ap_private &LHS, const ap_private &RHS, + ap_private &Quotient, ap_private &Remainder){ + assert(RHS!=0 && "Divide by 0"); + Quotient = LHS.VAl/RHS.VAl; + Remainder = LHS.VAL % RHS.VAL; + } + + INLINE static void udivrem(const ap_private &LHS, uint64_t RHS, + ap_private &Quotient, ap_private &Remainder){ + assert(RHS!=0 && "Divide by 0"); + Quotient = LHS.VAl/RHS; + Remainder = LHS.VAL % RHS; + } + + INLINE static void sdivrem(const ap_private &LHS, const ap_private &RHS, + ap_private &Quotient, ap_private &Remainder) { + if (LHS.isNegative()) { + if (RHS.isNegative()) + ap_private::udivrem(-LHS, -RHS, Quotient, Remainder); + else + ap_private::udivrem(-LHS, RHS, Quotient, Remainder); + Quotient = -Quotient; + Remainder = -Remainder; + } else if (RHS.isNegative()) { + ap_private::udivrem(LHS, -RHS, Quotient, Remainder); + Quotient = -Quotient; + } else { + ap_private::udivrem(LHS, RHS, Quotient, Remainder); + } + } + + INLINE static void sdivrem(const ap_private &LHS, int64_t RHS, + ap_private &Quotient, ap_private &Remainder) { + if (LHS.isNegative()) { + if (RHS<0) + ap_private::udivrem(-LHS, -RHS, Quotient, Remainder); + else + ap_private::udivrem(-LHS, RHS, Quotient, Remainder); + Quotient = -Quotient; + Remainder = -Remainder; + } else if (RHS<0) { + ap_private::udivrem(LHS, -RHS, Quotient, Remainder); + Quotient = -Quotient; + } else { + ap_private::udivrem(LHS, RHS, Quotient, Remainder); + } + } + + template INLINE bool eq(const ap_private<_AP_W1, _AP_S1>& RHS) const { + return (*this) == RHS; + } + + template INLINE bool ne(const ap_private<_AP_W1, _AP_S1>& RHS) const { + return !((*this) == RHS); + } + + /// Regards both *this and RHS as unsigned quantities and compares them for + /// the validity of the less-than relationship. + /// @returns true if *this < RHS when both are considered unsigned. + /// @brief Unsigned less than comparison + template INLINE bool ult(const ap_private<_AP_W1, _AP_S1, 1>& RHS) const { + uint64_t lhsZext = ((uint64_t(VAL)) << (64-_AP_W)) >> (64-_AP_W); + uint64_t rhsZext = ((uint64_t(RHS.VAL)) << (64-_AP_W1)) >> (64-_AP_W1); + return lhsZext < rhsZext; + } + + /// Regards both *this and RHS as signed quantities and compares them for + /// validity of the less-than relationship. + /// @returns true if *this < RHS when both are considered signed. + /// @brief Signed less than comparison + template INLINE bool slt(const ap_private<_AP_W1, _AP_S1, 1>& RHS) const { + int64_t lhsSext = ((int64_t(VAL)) << (64-_AP_W)) >> (64-_AP_W); + int64_t rhsSext = ((int64_t(RHS.VAL)) << (64-_AP_W1)) >> (64-_AP_W1); + return lhsSext < rhsSext; + } + + + /// Regards both *this and RHS as unsigned quantities and compares them for + /// validity of the less-or-equal relationship. + /// @returns true if *this <= RHS when both are considered unsigned. + /// @brief Unsigned less or equal comparison + template INLINE bool ule(const ap_private<_AP_W1, _AP_S1>& RHS) const { + return ult(RHS) || eq(RHS); + } + + /// Regards both *this and RHS as signed quantities and compares them for + /// validity of the less-or-equal relationship. + /// @returns true if *this <= RHS when both are considered signed. + /// @brief Signed less or equal comparison + template INLINE bool sle(const ap_private<_AP_W1, _AP_S1>& RHS) const { + return slt(RHS) || eq(RHS); + } + + /// Regards both *this and RHS as unsigned quantities and compares them for + /// the validity of the greater-than relationship. + /// @returns true if *this > RHS when both are considered unsigned. + /// @brief Unsigned greather than comparison + template INLINE bool ugt(const ap_private<_AP_W1, _AP_S1>& RHS) const { + return !ult(RHS) && !eq(RHS); + } + + /// Regards both *this and RHS as signed quantities and compares them for + /// the validity of the greater-than relationship. + /// @returns true if *this > RHS when both are considered signed. + /// @brief Signed greather than comparison + template INLINE bool sgt(const ap_private<_AP_W1, _AP_S1>& RHS) const { + return !slt(RHS) && !eq(RHS); + } + + /// Regards both *this and RHS as unsigned quantities and compares them for + /// validity of the greater-or-equal relationship. + /// @returns true if *this >= RHS when both are considered unsigned. + /// @brief Unsigned greater or equal comparison + template INLINE bool uge(const ap_private<_AP_W1, _AP_S1>& RHS) const { + return !ult(RHS); + } + + /// Regards both *this and RHS as signed quantities and compares them for + /// validity of the greater-or-equal relationship. + /// @returns true if *this >= RHS when both are considered signed. + /// @brief Signed greather or equal comparison + template INLINE bool sge(const ap_private<_AP_W1, _AP_S1>& RHS) const { + return !slt(RHS); + } + + INLINE ap_private abs() const { + if (isNegative()) + return -(*this); + return *this; + } + + ap_private<_AP_W, false> get() const { + ap_private<_AP_W,false> ret(*this); + return ret; + } + + INLINE static uint32_t getBitsNeeded(const char* str, uint32_t slen, uint8_t radix) { + return _AP_W; + } + + INLINE uint32_t getActiveBits() const { + uint32_t bits=_AP_W - countLeadingZeros(); + return bits?bits:1; + } + + INLINE double roundToDouble(bool isSigned=false) const { + const static uint64_t mask = ~0ULL << (APINT_BITS_PER_WORD - _AP_W); + return double(VAL); + } + + INLINE unsigned length() const { return _AP_W; } + + /*Reverse the contents of ap_private instance. I.e. LSB becomes MSB and vise versa*/ + INLINE ap_private& reverse () { + for (int i = 0; i < _AP_W/2; ++i) { + bool tmp = operator[](i); + if (operator[](_AP_W - 1 - i)) + set(i); + else + clear(i); + if (tmp) + set(_AP_W - 1 - i); + else + clear(_AP_W - 1 - i); + } + clearUnusedBits(); + return *this; + } + + /*Return true if the value of ap_private instance is zero*/ + INLINE bool iszero () const { + return isMinValue(); + } + + /* x < 0 */ + INLINE bool sign () const { + if (isNegative()) + return true; + return false; + } + + /* x[i] = !x[i] */ + INLINE void invert (int i) { + assert( i >= 0 && "Attempting to read bit with negative index"); + assert( i < _AP_W && "Attempting to read bit beyond MSB"); + flip(i); + } + + /* x[i] */ + INLINE bool test (int i) const { + assert( i >= 0 && "Attempting to read bit with negative index"); + assert( i < _AP_W && "Attempting to read bit beyond MSB"); + return operator[](i); + } + + //This is used for sc_lv and sc_bv, which is implemented by sc_uint + //Rotate an ap_private object n places to the left + INLINE void lrotate(int n) { + assert( n >= 0 && "Attempting to shift negative index"); + assert( n < _AP_W && "Shift value larger than bit width"); + operator = (shl(n) | lshr(_AP_W - n)); + } + + //This is used for sc_lv and sc_bv, which is implemented by sc_uint + //Rotate an ap_private object n places to the right + INLINE void rrotate(int n) { + assert( n >= 0 && "Attempting to shift negative index"); + assert( n < _AP_W && "Shift value larger than bit width"); + operator = (lshr(n) | shl(_AP_W - n)); + } + + //Set the ith bit into v + INLINE void set (int i, bool v) { + assert( i >= 0 && "Attempting to write bit with negative index"); + assert( i < _AP_W && "Attempting to write bit beyond MSB"); + v ? set(i) : clear(i); + } + + //Set the ith bit into v + INLINE void set_bit (int i, bool v) { + assert( i >= 0 && "Attempting to write bit with negative index"); + assert( i < _AP_W && "Attempting to write bit beyond MSB"); + v ? set(i) : clear(i); + } + + //Get the value of ith bit + INLINE bool get_bit (int i) const { + assert( i >= 0 && "Attempting to read bit with negative index"); + assert( i < _AP_W && "Attempting to read bit beyond MSB"); + return operator [](i); + } + + //complements every bit + INLINE void b_not() { + flip(); + } + + //Binary Arithmetic + //----------------------------------------------------------- +#define OP_BIN_AP(Sym,Rty, Fun) \ + template \ + INLINE \ + typename RType<_AP_W2,_AP_S2>::Rty \ + operator Sym (const ap_private<_AP_W2,_AP_S2>& op) const { \ + typename RType<_AP_W2,_AP_S2>::Rty lhs(*this); \ + typename RType<_AP_W2,_AP_S2>::Rty rhs(op); \ + return lhs.Fun(rhs); \ + } \ + + ///Bitwise and, or, xor + //OP_BIN_AP(&,logic, And) + //OP_BIN_AP(|,logic, Or) + //OP_BIN_AP(^,logic, Xor) + +#undef OP_BIN_AP + template + INLINE typename RType<_AP_W2,_AP_S2>::div + operator / (const ap_private<_AP_W2,_AP_S2>&op) const { + ap_private lhs=ap_private(*this); + ap_private rhs=ap_private(op); + return typename RType<_AP_W2,_AP_S2>::div((_AP_S||_AP_S2)?lhs.sdiv(rhs):lhs.udiv(rhs)); + } + + + template + INLINE typename RType<_AP_W2,_AP_S2>::mod + operator % (const ap_private<_AP_W2,_AP_S2>&op) const { + ap_private lhs=*this; + ap_private rhs=op; + typename RType<_AP_W2,_AP_S2>::mod res = typename RType<_AP_W2,_AP_S2>::mod (_AP_S?lhs.srem(rhs):lhs.urem(rhs)); + return res; + } + + +#define OP_ASSIGN_AP_2(Sym) \ + template \ + INLINE ap_private<_AP_W, _AP_S>& operator Sym##=(const ap_private<_AP_W2,_AP_S2>& op) \ + { \ + *this=operator Sym (op); \ + return *this; \ + } \ + + OP_ASSIGN_AP_2(/) + OP_ASSIGN_AP_2(%) +#undef OP_ASSIGN_AP_2 + + ///Bitwise assign: and, or, xor + //------------------------------------------------------------- + // OP_ASSIGN_AP(&) + // OP_ASSIGN_AP(^) + // OP_ASSIGN_AP(|) +#undef OP_ASSIGN_AP +#if 1 + + template + INLINE ap_private<_AP_W, _AP_S> + operator << (const ap_private<_AP_W2, _AP_S2>& op2) const { + uint32_t sh=op2.to_uint(); + return *this << sh; + } + + INLINE ap_private<_AP_W, _AP_S> + operator << (uint32_t sh) const { + return shl(sh); + } + +#endif + + template + INLINE ap_private<_AP_W, _AP_S> + operator >> (const ap_private<_AP_W2, _AP_S2>& op2) const { + uint32_t sh = op2.to_uint(); + return *this >> sh; + } + + INLINE ap_private<_AP_W, _AP_S> + operator >>(uint32_t sh) const { + ap_private<_AP_W, _AP_S> r(*this); + bool overflow=(sh>=_AP_W); + bool neg_v=r.isNegative(); + if(_AP_S) { + if(overflow) + neg_v?r.set():r.clear(); + else + return r.ashr(sh); + } else { + if(overflow) + r.clear(); + else + return r.lshr(sh); + } + return r; + } + + ///Shift assign + //------------------------------------------------------------------ +#define OP_ASSIGN_AP_3_SINGLE(Sym) \ + template \ + INLINE ap_private<_AP_W, _AP_S>& operator Sym##=(const ap_private<_AP_W2,_AP_S2>& op) \ + { \ + *this=operator Sym (op.getVal()); \ + return *this; \ + } + OP_ASSIGN_AP_3_SINGLE(>>) +#undef OP_ASSIGN_AP_3_SINGLE + + ///Comparisons + //----------------------------------------------------------------- + template + INLINE bool operator != (const ap_private<_AP_W2, _AP_S2, 1>& op) const { + return !(*this==op); + } + + template + INLINE bool operator > (const ap_private<_AP_W2, _AP_S2, 1>& op) const { + return op < *this; + } + + template + INLINE bool operator <= (const ap_private<_AP_W2, _AP_S2, 1>& op) const { + return !(*this>op); + } + + template + INLINE bool operator < (const ap_private<_AP_W2, _AP_S2, 1>& op) const { + enum { _AP_MAX_W = AP_MAX(_AP_W+(_AP_S||_AP_S2),_AP_W2+(_AP_S||_AP_S2))}; + ap_private<_AP_MAX_W, _AP_S> lhs(*this); + ap_private<_AP_MAX_W, _AP_S2> rhs(op); + if (_AP_S == _AP_S2) + return _AP_S?lhs.slt(rhs):lhs.ult(rhs); + else if (_AP_W < 32 && _AP_W2 < 32) + return lhs.slt(rhs); + else + if (_AP_S) + if (_AP_W2 >= _AP_W) + return lhs.ult(rhs); + else + return lhs.slt(rhs); + else + if (_AP_W >= _AP_W2) + return lhs.ult(rhs); + else + return lhs.slt(rhs); + } + + template + INLINE bool operator >=(const ap_private<_AP_W2, _AP_S2, 1>& op) const { + return !(*this + INLINE bool operator == (const ap_private<_AP_W2, _AP_S2, _AP_N2>& op) const { + return op == *this; + } + + template + INLINE bool operator != (const ap_private<_AP_W2, _AP_S2, _AP_N2>& op) const { + return !(op==*this); + } + + template + INLINE bool operator > (const ap_private<_AP_W2, _AP_S2, _AP_N2>& op) const { + return op < (*this); + } + + template + INLINE bool operator <= (const ap_private<_AP_W2, _AP_S2, _AP_N2>& op) const { + return op >= *this; + } + + template + INLINE bool operator <(const ap_private<_AP_W2, _AP_S2, _AP_N2>& op) const { + return op > *this; + } + + template + INLINE bool operator >=(const ap_private<_AP_W2,_AP_S2,_AP_N2>& op) const { + return op <= *this; + } + ///Bit and Part Select + //-------------------------------------------------------------- + INLINE ap_range_ref<_AP_W,_AP_S> + operator () (int Hi, int Lo) { + assert((Hi < _AP_W) && (Lo < _AP_W)&&"Out of bounds in range()"); + return ap_range_ref<_AP_W,_AP_S>(this, Hi, Lo); + } + + INLINE ap_range_ref<_AP_W,_AP_S> + operator () (int Hi, int Lo) const { + assert((Hi < _AP_W) && (Lo < _AP_W)&&"Out of bounds in range()"); + return ap_range_ref<_AP_W,_AP_S>(const_cast*>(this), Hi, Lo); + } + + INLINE ap_range_ref<_AP_W,_AP_S> + range (int Hi, int Lo) const { + assert((Hi < _AP_W) && (Lo < _AP_W)&&"Out of bounds in range()"); + return ap_range_ref<_AP_W,_AP_S>((const_cast*> (this)), Hi, Lo); + } + + INLINE ap_range_ref<_AP_W,_AP_S> + range (int Hi, int Lo) { + assert((Hi < _AP_W) && (Lo < _AP_W)&&"Out of bounds in range()"); + return ap_range_ref<_AP_W,_AP_S>(this, Hi, Lo); + } + + template + INLINE ap_range_ref<_AP_W,_AP_S> + range (const ap_private<_AP_W2, _AP_S2> &HiIdx, + const ap_private<_AP_W3, _AP_S3> &LoIdx) { + int Hi = HiIdx.to_int(); + int Lo = LoIdx.to_int(); + assert((Hi < _AP_W) && (Lo < _AP_W) && "Out of bounds in range()"); + return ap_range_ref<_AP_W,_AP_S>(this, Hi, Lo); + } + + template + INLINE ap_range_ref<_AP_W,_AP_S> + operator () (const ap_private<_AP_W2, _AP_S2> &HiIdx, + const ap_private<_AP_W3, _AP_S3> &LoIdx) { + int Hi = HiIdx.to_int(); + int Lo = LoIdx.to_int(); + assert((Hi < _AP_W) && (Lo < _AP_W) && "Out of bounds in range()"); + return ap_range_ref<_AP_W,_AP_S>(this, Hi, Lo); + } + + template + INLINE ap_range_ref<_AP_W,_AP_S> + range (const ap_private<_AP_W2, _AP_S2> &HiIdx, + const ap_private<_AP_W3, _AP_S3> &LoIdx) const { + int Hi = HiIdx.to_int(); + int Lo = LoIdx.to_int(); + assert((Hi < _AP_W) && (Lo < _AP_W) && "Out of bounds in range()"); + return ap_range_ref<_AP_W,_AP_S>(const_cast(this), Hi, Lo); + } + + template + INLINE ap_range_ref<_AP_W,_AP_S> + operator () (const ap_private<_AP_W2, _AP_S2> &HiIdx, + const ap_private<_AP_W3, _AP_S3> &LoIdx) const { + int Hi = HiIdx.to_int(); + int Lo = LoIdx.to_int(); + return this->range(Hi, Lo); + } + + + INLINE ap_bit_ref<_AP_W,_AP_S> operator [] (uint32_t index) { + assert(index >= 0&&"Attempting to read bit with negative index"); + assert(index < _AP_W && "Attempting to read bit beyond MSB"); + return ap_bit_ref<_AP_W,_AP_S> (*this, (int)index); + } + + template + INLINE ap_bit_ref<_AP_W,_AP_S> operator [] (const ap_private<_AP_W2,_AP_S2> &index) { + assert(index >= 0 && "Attempting to read bit with negative index"); + assert(index < _AP_W && "Attempting to read bit beyond MSB"); + return ap_bit_ref<_AP_W,_AP_S>( *this, index.to_int() ); + } + + template + INLINE bool operator [] (const ap_private<_AP_W2,_AP_S2>& index) const { + assert(index < _AP_W && "Attempting to read bit beyond MSB"); + ap_bit_ref<_AP_W,_AP_S> br =operator [] (index); + return br.to_bool(); + } + + INLINE ap_bit_ref<_AP_W,_AP_S> bit (int index) { + assert(index >= 0 && "Attempting to read bit with negative index"); + assert(index < _AP_W && "Attempting to read bit beyond MSB"); + return ap_bit_ref<_AP_W,_AP_S>( *this, index ); + } + + template + INLINE ap_bit_ref<_AP_W,_AP_S> bit (const ap_private<_AP_W2,_AP_S2> &index) { + assert(index >= 0 && "Attempting to read bit with negative index"); + assert(index < _AP_W &&"Attempting to read bit beyond MSB"); + return ap_bit_ref<_AP_W,_AP_S>( *this, index.to_int() ); + } + + INLINE bool bit (int index) const { + assert(index >= 0 && "Attempting to read bit with negative index"); + assert(index < _AP_W && "Attempting to read bit beyond MSB"); + ap_bit_ref<_AP_W,_AP_S> br(const_cast*>(this), index); + return br.to_bool(); + } + + template + INLINE bool bit (const ap_private<_AP_W2,_AP_S2>& index) const { + assert(index < _AP_W && "Attempting to read bit beyond MSB"); + ap_bit_ref<_AP_W,_AP_S> br = bit(index); + return br.to_bool(); + } + + template + INLINE ap_concat_ref<_AP_W,ap_private<_AP_W, _AP_S>,_AP_W2,ap_private<_AP_W2,_AP_S2> > concat(const ap_private<_AP_W2,_AP_S2>& a2) const { + return ap_concat_ref<_AP_W, ap_private<_AP_W, _AP_S>, _AP_W2, ap_private<_AP_W2,_AP_S2> >(const_cast& >(*this), + const_cast& >(a2)); + } + + template + INLINE ap_concat_ref<_AP_W,ap_private<_AP_W, _AP_S>,_AP_W2,ap_private<_AP_W2,_AP_S2> > concat(ap_private<_AP_W2,_AP_S2>& a2) { + return ap_concat_ref<_AP_W, ap_private<_AP_W, _AP_S>, _AP_W2, ap_private<_AP_W2,_AP_S2> >(*this, a2); + } + + template + INLINE ap_concat_ref<_AP_W, ap_private, _AP_W2, ap_private<_AP_W2, _AP_S2> > + operator, (const ap_private<_AP_W2, _AP_S2>& a2) const { + return ap_concat_ref<_AP_W, ap_private, _AP_W2, ap_private<_AP_W2, + _AP_S2> >(const_cast& >(*this), const_cast& >(a2)); + } + + template + INLINE ap_concat_ref<_AP_W, ap_private, _AP_W2, ap_private<_AP_W2, _AP_S2> > + operator, (const ap_private<_AP_W2, _AP_S2>& a2) { + return ap_concat_ref<_AP_W, ap_private, _AP_W2, ap_private<_AP_W2, + _AP_S2> >(*this, const_cast& >(a2)); + } + + template + INLINE ap_concat_ref<_AP_W, ap_private, _AP_W2, ap_private<_AP_W2, _AP_S2> > + operator, (ap_private<_AP_W2, _AP_S2>& a2) const { + return ap_concat_ref<_AP_W, ap_private, _AP_W2, ap_private<_AP_W2, + _AP_S2> >(const_cast& >(*this), a2); + } + + template + INLINE ap_concat_ref<_AP_W, ap_private, _AP_W2, ap_private<_AP_W2, _AP_S2> > + operator, (ap_private<_AP_W2, _AP_S2>& a2) { + return ap_concat_ref<_AP_W, ap_private, _AP_W2, ap_private<_AP_W2, + _AP_S2> >(*this, a2); + } + + template + INLINE ap_concat_ref<_AP_W, ap_private<_AP_W, _AP_S>, _AP_W2, ap_range_ref<_AP_W2, _AP_S2> > + operator, (const ap_range_ref<_AP_W2, _AP_S2> &a2) const { + return ap_concat_ref<_AP_W, ap_private<_AP_W, _AP_S>, _AP_W2, + ap_range_ref<_AP_W2, _AP_S2> >(const_cast& >(*this), + const_cast& >(a2)); + } + + template + INLINE ap_concat_ref<_AP_W, ap_private<_AP_W, _AP_S>, _AP_W2, ap_range_ref<_AP_W2, _AP_S2> > + operator, (ap_range_ref<_AP_W2, _AP_S2> &a2) { + return ap_concat_ref<_AP_W, ap_private<_AP_W, _AP_S>, _AP_W2, + ap_range_ref<_AP_W2, _AP_S2> >(*this, a2); + } + + template + INLINE ap_concat_ref<_AP_W, ap_private<_AP_W, _AP_S>, 1, ap_bit_ref<_AP_W2, _AP_S2> > + operator, (const ap_bit_ref<_AP_W2, _AP_S2> &a2) const { + return ap_concat_ref<_AP_W, ap_private<_AP_W, _AP_S>, 1, + ap_bit_ref<_AP_W2, _AP_S2> >(const_cast& >(*this), + const_cast& >(a2)); + } + + template + INLINE ap_concat_ref<_AP_W, ap_private<_AP_W, _AP_S>, 1, ap_bit_ref<_AP_W2, _AP_S2> > + operator, (ap_bit_ref<_AP_W2, _AP_S2> &a2) { + return ap_concat_ref<_AP_W, ap_private<_AP_W, _AP_S>, 1, + ap_bit_ref<_AP_W2, _AP_S2> >(*this, a2); + } + + template + INLINE ap_concat_ref<_AP_W, ap_private<_AP_W, _AP_S>, _AP_W2+_AP_W3, ap_concat_ref<_AP_W2, _AP_T2, _AP_W3, _AP_T3> > + operator, (const ap_concat_ref<_AP_W2, _AP_T2, _AP_W3, _AP_T3> &a2) const { + return ap_concat_ref<_AP_W, ap_private<_AP_W, _AP_S>, _AP_W2+_AP_W3, + ap_concat_ref<_AP_W2, _AP_T2, _AP_W3, _AP_T3> >(const_cast& >(*this), + const_cast& >(a2)); + } + + template + INLINE ap_concat_ref<_AP_W, ap_private<_AP_W, _AP_S>, _AP_W2+_AP_W3, ap_concat_ref<_AP_W2, _AP_T2, _AP_W3, _AP_T3> > + operator, (ap_concat_ref<_AP_W2, _AP_T2, _AP_W3, _AP_T3> &a2) { + return ap_concat_ref<_AP_W, ap_private<_AP_W, _AP_S>, _AP_W2+_AP_W3, + ap_concat_ref<_AP_W2, _AP_T2, _AP_W3, _AP_T3> >(*this, a2); + } + + template + INLINE ap_concat_ref<_AP_W, ap_private, _AP_W2, af_range_ref<_AP_W2, _AP_I2, _AP_S2, _AP_Q2, _AP_O2, _AP_N2> > + operator, (const af_range_ref<_AP_W2, _AP_I2, _AP_S2, _AP_Q2, + _AP_O2, _AP_N2> &a2) const { + return ap_concat_ref<_AP_W, ap_private, _AP_W2, af_range_ref<_AP_W2, + _AP_I2, _AP_S2, _AP_Q2, _AP_O2, _AP_N2> >(const_cast& >(*this), + const_cast& >(a2)); + } + + template + INLINE ap_concat_ref<_AP_W, ap_private, _AP_W2, af_range_ref<_AP_W2, _AP_I2, _AP_S2, _AP_Q2, _AP_O2, _AP_N2> > + operator, (af_range_ref<_AP_W2, _AP_I2, _AP_S2, _AP_Q2, + _AP_O2, _AP_N2> &a2) { + return ap_concat_ref<_AP_W, ap_private, _AP_W2, af_range_ref<_AP_W2, + _AP_I2, _AP_S2, _AP_Q2, _AP_O2, _AP_N2> >(*this, a2); + } + + template + INLINE ap_concat_ref<_AP_W, ap_private, 1, af_bit_ref<_AP_W2, _AP_I2, _AP_S2, _AP_Q2, _AP_O2, _AP_N2> > + operator, (const af_bit_ref<_AP_W2, _AP_I2, _AP_S2, _AP_Q2, + _AP_O2, _AP_N2> &a2) const { + return ap_concat_ref<_AP_W, ap_private, 1, af_bit_ref<_AP_W2, + _AP_I2, _AP_S2, _AP_Q2, _AP_O2, _AP_N2> >(const_cast& >(*this), + const_cast& >(a2)); + } + + template + INLINE ap_concat_ref<_AP_W, ap_private, 1, af_bit_ref<_AP_W2, _AP_I2, _AP_S2, _AP_Q2, _AP_O2, _AP_N2> > + operator, (af_bit_ref<_AP_W2, _AP_I2, _AP_S2, _AP_Q2, + _AP_O2, _AP_N2> &a2) { + return ap_concat_ref<_AP_W, ap_private, 1, af_bit_ref<_AP_W2, + _AP_I2, _AP_S2, _AP_Q2, _AP_O2, _AP_N2> >(*this, a2); + } + + template + INLINE ap_private + operator & (const ap_concat_ref<_AP_W2, _AP_T2, _AP_W3, _AP_T3>& a2) { + return *this & a2.get(); + } + + template + INLINE ap_private + operator | (const ap_concat_ref<_AP_W2, _AP_T2, _AP_W3, _AP_T3>& a2) { + return *this | a2.get(); + } + + template + INLINE ap_private + operator ^ (const ap_concat_ref<_AP_W2, _AP_T2, _AP_W3, _AP_T3>& a2) { + return *this ^ a2.get(); + } + + + //Reduce operation + //----------------------------------------------------------- + INLINE bool and_reduce() const { + return (VAL & mask) == mask; + } + + INLINE bool nand_reduce() const { + return (VAL & mask) != mask; + } + + INLINE bool or_reduce() const { + return (bool)VAL; + } + + INLINE bool nor_reduce() const { + return VAL==0; + } + + INLINE bool xor_reduce() const { + unsigned int i=countPopulation(); + return (i%2)?true:false; + } + + INLINE bool xnor_reduce() const { + unsigned int i=countPopulation(); + return (i%2)?false:true; + } + + INLINE std::string to_string(uint8_t radix=2, bool sign=false) const { + return toString(radix, radix==10?_AP_S:sign); + } +}; +template +std::string ap_private<_AP_W, _AP_S, 1>::toString(uint8_t radix, bool wantSigned) const { + assert((radix == 10 || radix == 8 || radix == 16 || radix == 2) && + "Radix should be 2, 8, 10, or 16!"); + static const char *digits[] = { + "0","1","2","3","4","5","6","7","8","9","a","b","c","d","e","f" + }; + std::string result; + if (radix != 10) { + // For the 2, 8 and 16 bit cases, we can just shift instead of divide + // because the number of bits per digit (1,3 and 4 respectively) divides + // equaly. We just shift until there value is zero. + + // First, check for a zero value and just short circuit the logic below. + if (*this == (uint64_t)(0)) + result = "0"; + else { + ap_private<_AP_W, false, 1> tmp(*this); + size_t insert_at = 0; + if (wantSigned && isNegative()) { + // They want to print the signed version and it is a negative value + // Flip the bits and add one to turn it into the equivalent positive + // value and put a '-' in the result. + tmp.flip(); + tmp++; + result = "-"; + insert_at = 1; + } + // Just shift tmp right for each digit width until it becomes zero + uint32_t shift = (radix == 16 ? 4 : (radix == 8 ? 3 : 1)); + uint64_t mask = radix - 1; + ap_private<_AP_W, false, 1> zero(0); + while (tmp.ne(zero)) { + unsigned digit = (unsigned)(tmp.VAL & mask); + result.insert(insert_at, digits[digit]); + tmp = tmp.lshr(shift); + } + } + return result; + } + + ap_private<_AP_W, false, 1> tmp(*this); + ap_private<6, false, 1> divisor(radix); + ap_private<_AP_W, _AP_S, 1> zero(0); + size_t insert_at = 0; + if (wantSigned && isNegative()) { + // They want to print the signed version and it is a negative value + // Flip the bits and add one to turn it into the equivalent positive + // value and put a '-' in the result. + tmp.flip(); + tmp++; + result = "-"; + insert_at = 1; + } + if (tmp == ap_private<_AP_W, false, 1>(0ULL)) + result = "0"; + else while (tmp.ne(zero)) { + ap_private<_AP_W, false, 1> APdigit = tmp%divisor; + ap_private<_AP_W, false, 1> tmp2 = tmp/divisor; + uint32_t digit = (uint32_t)(APdigit.getZExtValue()); + assert(digit < radix && "divide failed"); + result.insert(insert_at,digits[digit]); + tmp = tmp2; + } + return result; + +} + +#endif /* #ifndef LLVM_SUPPORT_MATHEXTRAS_H */ \ No newline at end of file diff --git a/router/main.cpp b/router/main.cpp new file mode 100644 index 0000000..566bfd3 --- /dev/null +++ b/router/main.cpp @@ -0,0 +1,69 @@ +#include "router.hpp" + +int main(int argc, char *argv[]){ + + short int size_x = 10, size_y = 10; + short int line_num = 6; + + short int board[10][10], board_str[100]; + + int x, y; + for(y = 0; y < size_y; y++) { + for(x = 0; x < size_x; x ++) { + board[y][x] = 0; + } + } + + // Terminal cells (value > 0) + board[0][1] = 1; + board[7][1] = 1; + board[0][3] = 2; + board[8][4] = 2; + board[4][5] = 3; + board[6][5] = 3; + board[4][6] = 4; + board[7][2] = 4; + board[5][4] = 5; + board[6][6] = 5; + board[9][8] = 6; + board[9][9] = 6; + + // Routing disenabled cells (value < 0) + board[0][0] = -1; + board[1][7] = -1; + board[1][8] = -1; + board[2][1] = -1; + board[2][7] = -1; + board[2][8] = -1; + board[3][1] = -1; + board[4][1] = -1; + board[5][1] = -1; + + // Transform "board" to "board_str" + for(y = 0; y < size_y; y++) { + for(x = 0; x < size_x; x++) { + int idx = y * size_x + x; + board_str[idx] = board[y][x]; + } + } + + /** top function of router **/ + // status = 1: OK + // status = 0: NG + int status = router(size_x, size_y, line_num, board_str); + + /** top function of router (User can set "seed" value manually when calling this function.) **/ + //int status = router(size_x, size_y, line_num, board_str, 1234567); + + cout << "Router status: " << status << endl; + + // Transform "board_str" to "board" + for(y = 0; y < size_y; y++) { + for(x = 0; x < size_x; x++) { + int idx = y * size_x + x; + board[y][x] = board_str[idx]; + } + } + + return 0; +} diff --git a/router/main.o b/router/main.o new file mode 100644 index 0000000000000000000000000000000000000000..1359535f3013d8143148de8b2bdcd21a1154e57e GIT binary patch literal 3728 zcmbtXZ)jUp6u)h%>;8~tbDNtJjc{cv*pS!OxJ}g5CR?ImD{Cj>zqgk(p>b&v@?K^q zqMHlaxF|!)6d7Zv$UZ3S!;rQcTV#W=uYM8+vJZaPhk@G%hlo(m@4kE6yVpbz54?BI z{hi-E=iK|wyD#}5p4!#f(ZQ5-u;nT-+B<_R z*YkUGbgq*a7Zyn75i4=@_Bqm*d}Lq7t*1A}1LKL~T~BUEQ0>glcV6LQ7@P|85g2&BgEkj~ZL-~q(ym$71e zP+BwmGzdMV6c5b1iDG=GbUOTP%-SV~7y0KRXoKGrL1R4OdSXN>825~YxY0Cjh+yGd ztlkhskTJ&JiyPO;IK^k=%soakM|c|RI%Hh$>1}XqevUTeGtw02XRIPf_Ru``G;Z7g zFai>)je>eYP;>S3{D_OYJ7L^|^KVIX-~B>xUW+Rp}QgpG=EjekixajlE*2&22kdG{@f z$mVgvSNtLG@H(R}@ip!7UmLkN~Q zcDs8iz&s#Ng2Xj6sSw>fcD4J8!l8E$5AO_a+n=r$ooevu&|oOs7paPo@xBoWg$F~1 z(d#;b{b3^#j)Zs6wDmGZ$GiJj$5fzW%bFG4C#X6=4y&RE?4<)L0w*tv2}gZSWu4;CI{LowQM{>Ujisi^sdQ4gZBUIGeQc z#ZabPX6EkH-WP{brfFBxX3_-C%-2Sp)OOR%m-5BDL&MZyA!k>}h*ZP}$hPef`x&cj zR`W$CnaU6J$KztwV21p{G9so~vYkrSnl$r8J6my*nNi0uG80zCbShTfv6Gp2d>>&0 zY0J)M6gxR)j)l$mXv7?Od33-mP_#XxrGg#LyBV^@@xp%&#b|wwl{si;CJvf8EAK{i zw&zQ>N!hc5Nm}Tz5kEx4al2$rSd=9zQhP`-mz0^ZOv}km(e^;Tkk14P&+Tt~)=0jQ zI66^(o6c(ZTJkCRL5s7FKo#eF8@~AT6A$i(H2zOo9GqDy&TksNLBs#h;^Q<>z4w>K z->C5yH2%YcE9sI)4A!g1S*hWh6q&SN;s}R#Q`Naa!}Zf?v&3-{=y=e>|I^+6#dDKh z1Ga)Lbv^~jh9EC+B?)OLT=7}RK0N7IY0^%`)f391E^t_A+;S`yO4~LIRZ19uX@m?G zfF+^nB4wFS9H<3-|)`gN^YF??dI$61|q4xgbjI$ zF2wA|K$EDny?m8l>1T-t+q?b|Ip3?)JcaKioOqVXxGC#hn zx~TnA`W>okY7ytkO literal 0 HcmV?d00001 diff --git a/router/router.cpp b/router/router.cpp new file mode 100644 index 0000000..a5a6af6 --- /dev/null +++ b/router/router.cpp @@ -0,0 +1,338 @@ +#include "router.hpp" + +// DATA_BIT: bit length of cell idx +// PRIO_BIT: bit length of cost(priority) +int router(short int size_x, short int size_y, short int line_num, short int board_str[], ap_uint<32> seed){ + ap_uint board_str_len = size_x * size_y; + ap_uint j; + + ap_uint terminals[MAX_LINES][2]; + short int paths_size[MAX_LINES]; + ap_uint paths[MAX_LINES][MAX_PATH]; + bool adjacents[MAX_LINES]; + + ap_uint weights[MAX_CELLS]; + + short int i, x, y, p; + + // Line init. + for(i = 0; i < line_num; i++) { + terminals[i][0] = DATA_MAX; + terminals[i][1] = DATA_MAX; + paths_size[i] = 0; + adjacents[i] = false; + } + for(j = 0; j < board_str_len; j++) { + weights[j] = 1; // init. value is "1" + i = board_str[j]; + if(i > 0) { + if(terminals[i-1][0] == DATA_MAX) { terminals[i-1][0] = j; } + else if(terminals[i-1][1] == DATA_MAX) { terminals[i-1][1] = j; } + else { + cout << "Error: line#" << i << endl; + exit(1); + } + weights[j] = PRIO_MAX; + } + else if(i < 0) { + weights[j] = PRIO_MAX; + } + } + +#ifdef PRINT_BOARD + cout << "== Print board ==" << endl; + for(y = 0; y < size_y; y++) { + for(x = 0; x < size_x; x++) { + j = y * size_x + x; + i = board_str[j]; + if(i == 0) { cout << "-"; } + else if(i == -1) { cout << "X"; } + else{ cout << i; } + if(x != size_x-1) { cout << " "; } + } + cout << endl; + } +#endif + for(i = 0; i < line_num; i++) { + ap_uint t1 = terminals[i][0]; + ap_uint t2 = terminals[i][1]; + short int t1_x = t1 % size_x; + short int t1_y = t1 / size_x; + short int t2_x = t2 % size_x; + short int t2_y = t2 / size_x; + short int dist = abs(t1_x - t2_x) + abs(t1_y - t2_y); // Manhattan dist. + if(dist == 1) { + adjacents[i] = true; +#ifdef PRINT_BOARD + cout << "Line #" << i + 1 << " needs no routing" << endl; +#endif + } + } + + + lfsr_random_init(seed); + + // Step 1 + cout << "1st routing ..." << endl; + for(i = 0; i < line_num; i++) { + if(adjacents[i]) continue; +#ifdef PRINT_SEARCH + cout << "Line #" << i + 1 << endl; +#endif + ap_uint t1 = terminals[i][0]; + ap_uint t2 = terminals[i][1]; + weights[t1] = 1; + if(search(size_x, size_y, &paths_size[i], paths[i], t1, t2, weights) < 0) { return 0; } + weights[t1] = PRIO_MAX; + } + + bool has_overlap; + ap_uint<1> overlap_checks[MAX_CELLS]; + + // Step 2 + cout << "rip-up routing ..." << endl; + short int last_target = -1; + ap_uint<16> round; + for(round = 1; round <= ROUND_LIMIT; round++) { + short int target = lfsr_random() % line_num; + if(adjacents[target]) continue; + if(target == last_target) continue; + last_target = target; + ap_uint round_weight = new_weight(round); + +#ifdef PRINT_SEARCH + cout << "Line #" << target + 1 << "(round: " << round << ", weight: " << round_weight << ")" << endl; +#endif + + ap_uint t1 = terminals[target][0]; + ap_uint t2 = terminals[target][1]; + + for(p = 0; p < paths_size[target]; p++) { + weights[paths[target][p]] = 1; + } + for(i = 0; i < line_num; i++) { + if(i == target) continue; + for(p = 0; p < paths_size[i]; p++) { + weights[paths[i][p]] = round_weight; + } + } + weights[t1] = 1; + search(size_x, size_y, &paths_size[target], paths[target], t1, t2, weights); + weights[t1] = PRIO_MAX; + + has_overlap = false; + for(j = 0; j < board_str_len; j++) { + i = board_str[j]; + if(i > 0 || i < 0) { overlap_checks[j] = 1; } + else { overlap_checks[j] = 0; } + } + for(i = 0; i < line_num; i++) { + for(p = 0; p < paths_size[i]; p++) { + ap_uint cell_id = paths[i][p]; + if(overlap_checks[cell_id]) { + has_overlap = true; + break; + } + overlap_checks[cell_id] = 1; + } + } + if(!has_overlap) break; + } + + /** //debug + for(j = 0; j < board_str_len; j++) { + i = board_str[j]; + cout << i << ": " << weights[j] << endl; + } + **/ + + if(has_overlap) { // Cannot solve + return 0; + } + + int total_wire_length = 0; + for(i = 0; i < line_num; i++) { + total_wire_length += paths_size[i]; + for(p = 0; p < paths_size[i]; p++) { + ap_uint cell_id = paths[i][p]; + board_str[cell_id] = i + 1; + } + } + +#ifdef PRINT_BOARD + cout << "== Print answer ==" << endl; + for(y = 0; y < size_y; y++) { + for(x = 0; x < size_x; x++) { + j = y * size_x + x; + i = board_str[j]; + if(i == 0) { cout << "-"; } + else if(i == -1) { cout << "X"; } + else{ cout << i; } + if(x != size_x-1) { cout << " "; } + } + cout << endl; + } +#endif + + return total_wire_length; +} + +void lfsr_random_init(ap_uint<32> seed) { + lfsr = seed; +} + +ap_uint<32> lfsr_random() { + bool b_32 = lfsr.get_bit(32-32); + bool b_22 = lfsr.get_bit(32-22); + bool b_2 = lfsr.get_bit(32-2); + bool b_1 = lfsr.get_bit(32-1); + bool new_bit = b_32 ^ b_22 ^ b_2 ^ b_1; + lfsr = lfsr >> 1; + lfsr.set_bit(31, new_bit); + return lfsr.to_uint(); +} + +ap_uint new_weight(ap_uint<16> x) { + ap_uint<16> y = (x & 0x00FF) + 1; + return (ap_uint)(y); +} + +int search(short int size_x, short int size_y, short int *path_size, ap_uint path[MAX_PATH], ap_uint start, ap_uint goal, ap_uint w[MAX_CELLS]){ + + ap_uint dist[MAX_CELLS]; + ap_uint prev[MAX_CELLS]; + + int j; + for(j = 0; j < MAX_CELLS; j++) { + dist[j] = PRIO_MAX; + } + + ap_uint pq_len = 0; + bool is_empty = true; + ap_uint pq_nodes[MAX_PQ]; + + short int goal_x = goal % size_x; + short int goal_y = goal / size_x; + + dist[start] = 0; + enqueue(pq_nodes, 0, start, &pq_len, &is_empty); + + bool find_path = false; // No path exists + while(!is_empty) { + + ap_uint prev_cost; + ap_uint s; + dequeue(pq_nodes, &prev_cost, &s, &pq_len, &is_empty); + + ap_uint dist_s = dist[s]; + + if(s == goal) { + find_path = true; + break; + } + + ap_uint cost = w[s]; + short int s_x = s % size_x; + short int s_y = s / size_x; + + int a; + for(a = 0; a < 4; a++) { + short int d_x = s_x; + short int d_y = s_y; + switch(a) { + case 0: d_x -= 1; break; + case 1: d_x += 1; break; + case 2: d_y -= 1; break; + case 3: d_y += 1; break; + } + if(d_x >= 0 && d_x < size_x && d_y >= 0 && d_y < size_y) { + ap_uint d = d_y * size_x + d_x; + if(w[d] == PRIO_MAX && d != goal) continue; + + ap_uint dist_d = dist_s + cost; + if(dist_d < dist[d]) { + dist[d] = dist_d; + prev[d] = s; + dist_d += abs(d_x - goal_x) + abs(d_y - goal_y); + enqueue(pq_nodes, dist_d, d, &pq_len, &is_empty); + } + } + } + } + if(!find_path){ return -1; } + + ap_uint t = prev[goal]; + short int p = 0; +#ifdef PRINT_SEARCH + cout << "Path: "; +#endif + while(t != start) { +#ifdef PRINT_SEARCH + cout << "(" << (short int)t % size_x << ", " << (short int)t / size_x << ")"; +#endif + path[p] = t; + p++; + t = prev[t]; + } +#ifdef PRINT_SEARCH + cout << endl; +#endif + *path_size = p; + + return 0; +} + +// Enqueue (Insert an element) +void enqueue(ap_uint pq_nodes[MAX_PQ], ap_uint priority, ap_uint data, ap_uint *pq_len, bool *is_empty){ + + (*pq_len)++; + if ((*pq_len) == 0) { (*pq_len)--; } // Queue is full -> Last element is automatically removed + // Note that last element is not always the lowest priority one. // + + ap_uint i = (*pq_len); + ap_uint p = (*pq_len) >> 1; // parent node + while (i > 1 && (ap_uint)(pq_nodes[p] >> DATA_BIT) >= priority) { + pq_nodes[i] = pq_nodes[p]; + i = p; + p = p >> 1; // parent node + } + pq_nodes[i] = ((ap_uint)priority << DATA_BIT) | (ap_uint)data; + *is_empty = false; +} + +// Dequeue (Extract and remove the top element) +void dequeue(ap_uint pq_nodes[MAX_PQ], ap_uint *ret_priority, ap_uint *ret_data, ap_uint *pq_len, bool *is_empty){ + + *ret_priority = (ap_uint)(pq_nodes[1] >> DATA_BIT); + *ret_data = (ap_uint)(pq_nodes[1] & DATA_MASK); + + ap_uint i = 1; // root node + ap_uint last_priority = (ap_uint)(pq_nodes[*pq_len] >> DATA_BIT); // Priority of last element + + while (!(i >> (PQ_BIT-1))) { + ap_uint c1 = i << 1; // child node (L) + ap_uint c2 = c1 + 1; // child node (R) + if (c1 < *pq_len && (ap_uint)(pq_nodes[c1] >> DATA_BIT) <= last_priority) { + if (c2 < *pq_len && (ap_uint)(pq_nodes[c2] >> DATA_BIT) <= (ap_uint)(pq_nodes[c1] >> DATA_BIT)) { + pq_nodes[i] = pq_nodes[c2]; + i = c2; + } + else { + pq_nodes[i] = pq_nodes[c1]; + i = c1; + } + } + else { + if (c2 < *pq_len && (ap_uint)(pq_nodes[c2] >> DATA_BIT) <= last_priority) { + pq_nodes[i] = pq_nodes[c2]; + i = c2; + } + else { + break; + } + } + } + pq_nodes[i] = pq_nodes[*pq_len]; + (*pq_len)--; + if ((*pq_len) == 0) { *is_empty = true; } +} diff --git a/router/router.hpp b/router/router.hpp new file mode 100644 index 0000000..a2fcdab --- /dev/null +++ b/router/router.hpp @@ -0,0 +1,44 @@ +#ifndef __ROUTER_HPP__ +#define __ROUTER_HPP__ + +#include +#define SOFTWARE +#ifdef SOFTWARE + #include "ap_int.h" +#else + #include +#endif + +using namespace std; + +#define ROUND_LIMIT 32768 // Max=65534(=2^16-2) +#define PRINT_BOARD +//#define PRINT_SEARCH // for router debug + +#define MAX_LINES 256 +#define MAX_PATH 128 +#define MAX_CELLS 16384 // 128x128 + +#define PQ_BIT 12 +#define MAX_PQ 4096 + +#define PRIO_BIT 16 +#define DATA_BIT 16 +#define ELEM_BIT 32 // ELEM_BIT = PRIO_BIT + DATA_BIT + +#define DATA_MASK 65535 // 0000 FFFF +#define DATA_MAX 65535 // FFFF +#define PRIO_MAX 65535 // FFFF +/** top function (User can set "seed" value manually when calling this function.) **/ +int router(short int size_x, short int size_y, short int line_num, short int board_str[], ap_uint<32> seed = 12345); + +static ap_uint<32> lfsr; +void lfsr_random_init(ap_uint<32> seed); +ap_uint<32> lfsr_random(); +ap_uint new_weight(ap_uint<16> x); + +int search(short int size_x, short int size_y, short int *path_size, ap_uint path[MAX_PATH], ap_uint start, ap_uint goal, ap_uint w[MAX_CELLS]); +void enqueue(ap_uint pq_nodes[MAX_PQ], ap_uint priority, ap_uint data, ap_uint *pq_len, bool *is_empty); +void dequeue(ap_uint pq_nodes[MAX_PQ], ap_uint *ret_priority, ap_uint *ret_data, ap_uint *pq_len, bool *is_empty); + +#endif /* __ROUTER_HPP__ */ diff --git a/router/router.o b/router/router.o new file mode 100644 index 0000000000000000000000000000000000000000..cd4e64dc8ac23b3bb9dc44eaf1e54ec42363d38f GIT binary patch literal 14816 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 lk5_gg-Y5cWJqd?GzKb63{FFOPH2b3`q@1oF9N* z9|ULO^*9WrmV3+Xhu6ou_4dcTzFS@&&j96-1e8F%?G4l)^y1ZMsm=)0KwAtv>)h|! zXYa{mn6!PrKJSmmfy~-#?X}ikd+)XPUVERJy}{#KTwt+C;wg~skq8^P%E?IPrzBN> zg`u2QEnO)&r5Vx<(iNZ-;m^r(2%0GYN4aVNOE_O4pcQ}B1ty`oz{wH<-e8hZg82vw z2~v4ukCP`&c(U9?1(YO(5lD_~9a+Foz($r3a3{B;gp6X3!aj*ia#QbNC}1N?2sq3Q z6HwHT)X-l8*V|Cw1V*@%faGSMV^9=Z_v>&ArMKQ@GHkug$r1v_OtK`PkoyYc$j(3a zv2(_yyu69p#m?;)kXKi_qrGiqRplM+EwkI(IwI?4udA+_T~%2g>MWnb>P`BI_r4{| zSV^KC6<}m@DgMX@C_i+=JG)lTy=VI?QtHfw8(lN2Ug-G-R_$tm~3~{~CR%e^py3><=z# zZwiI{AxZZ()aot%ASXA}E^6=W@HaHAZ1kR2Dn?n9dZ%13$?eMIT zbkIBJc16OTW=cO$AD-77eyYpwZT2|k>b3gXwibVf-UfEYTpxB+>3U}<9P~G>207#p zhP}<8I+|OXf_gaE)D{jw*0U6}xhSfwS#WzB^o9!EQ(vXmJy1VaZ%1+U;Yxo;OZ)${ z0wzj^gj<81Yf+;Xy}2nAHfxhp%SF7F*)^+f=`<_GDh(@|J0oGUDdq**BcWE&Fzq2v zn@LA1B%!mKML(g7nxD{{Tc6MaO>L-*PQ8Op<5=^$CcP=_U)Kh`I?3@qUES2yA>HTm zE?lI~DX+|==9JGf)619ZbIU8sYsO&?M>a}+Q-FW;6yl$iVU(h$2-p>jLOk6401Kpl z1VZyh1^!Cg+ODD%<2q^|DJR44B%Hb;Rl)E%gij${ zVfd|tV+=?sJHuxZPF<0b82;=$MG9;I&K_#Fz9Cnmlw641z1z^d`w8u%1t9r2Xxd=W z^!bX^4?Umi!>3+PG^cAXwW#YS^tp$!YY3@tbUE87ISo;`XW=h zNgZZN-Ku8hxWUx!IPXY%9Q}?HOj$+1ZERvjAkm;c<8d58V!OJPOD=Kr2S8s*^;+XN zBA0DaX;KKFK{f+I&oQcng0yQdwW-H(f(UiQMAkZqbqiw+7`xPNlWw+z<2+@)$TRn; zv|>{Uv{F0Lup_3%h#zn(AX(i{${QJRle!&HOYmw^J)Q%>wTC>HmE8yxTh-?ocTD|j z%G}E{&4#DSZB;4YBip_M$nwdC3P#+g?jT5({4Emu$*H}@a34Xkq|40RuD)OZir8+XF;1Mm6It&3M~5stx>Rk~Z+kjoQ(a=6FjR_;`k9T=iGP>2oQr;73CnxY z0NvV^N0IXvOu9rfoUDE2SFR^r(E}FE_=0AvBVu-Y)T0CIvZf*oXGgylxA+o1Rq
M74yeZ9sJ zU;IYz!28xE@lx3(_nz<=N4*0nyRYW;wGQNJ1H)F$n4)^2&nQLX93~x5bOeS#ZiaW@ z!VGWpf@Q-lDDoI5NWeSrE4y#>J5|~l7 zK?|$KAkySId(v2cG|XSsyNRBfi!Mt3_yYQAi|ZlRGS^Sw`I4()S>DEyd+)o31{?AC z5-rp!7;##n9pxBTAQw$ipvAwaB^s!88q}$pah!~nd)>taRI2^dnvB1CjRS7EH>}#d z10PtumW#FVTRldK8mPAB=kl{r6r$C1p3 z>EUO2GidSB;!{;(e4;18YgLyRx6kkz2UGW>H1gOiW~u})QA;dJdyQ*MgM0enj}a?+ z-;&e&SFzrI%(cSxnCtO_$>X1n&0nssvL2?s-FSMIw$##>%K@%b=9dfH1&}T9AdCFkQ z2_h`8KsTSSbL}`_+A&Nba$gt~N^EDVFeyqBHSQ*t-L96C(a8h7Ut@!_6kg zCbgSs3#+rJrlf=(_#`PXe&IN#eG2u6h{()pEe_%V$if1QA1aqwC9E8bl~Q-oqZt>; z0Ez}Q1HNtAojiRpo$h`{-5|+5cO&AE``qgFP+uwc9Ryf``NNDZsL#-_tP-Sy8BO6r zHxXefWzs{Mw-JQk4uZ%dNDpkK>>nVR{3g~oExz64iHFhTux=+~+NaVgB1XVnH_E;H ztfp6*9CB(_nxO-@g>yx)M<=^I>00Mo`k!i zK}EkA11?PK#&Oma?!=R6m+?~#th40a2K9Q6@q5>&Zw6cgXJjD}aMzsEjDs#?Q2vko zt}nk9sQKxqM-$7^E}(&dlQVlBBI2~X^d z+qmd9&dRZkU^N2qazkn4-DP)p<=q1b)uap0DpQ~iuj zscMw34SZzvZoK<0@(4LbzVCy34-+(A;&3~2bD~qD)+VfXp)ID?*8EETOFDIm{=ph9 zi@s(-MPRzzLo*U4Y2!$s=g7K`0yPN9*AJ(b@p;Pho!FayNT*p?OkGNI0hXd0SSTg; z7^oz|DVl5^<#Uot$Fkgw!X(H$q(r?X{0d4)r9a0S#Nq;1;(iO7<<<{$ILBPz-lxQ`@kzoy`H3p0lM}O)m6trjfR;RT0zg>$cy9M!O-!u3~I?rO6 ze;prN#^MvP9=MD*metFB?`p=+urO4scJyG@er*;A*e>)9Vjf&hv;Sf=_7n{PP#3KV zZuv(CvGCD~(MW5@I_$li*;BRLJ2rzGXEiA3qDnr`+6+4$Op{t-x1<0-hc;#(mSwwG zBLW5!oXlok}0K@));rZ5qnv0RQ$y*ea zir+#DohU1_ZehI$MDJFm^**^5K_12-8S6{zQWZ=>iMlkJ1rC6K)8jaHC}vgA{m@cO zBQW4GN*7ZwsSVzT%{b`MK}D+>ioD@~SkDn3%I*hyWJ8L~qjgX2`(>g&tu

`k+YL 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 literal 0 HcmV?d00001 diff --git a/solve b/solve index e358e7a17d2ee502eade2b6bd76dc50493e17bae..080fe21197bb8c0c0ad65cbfa6bcdda00337b43a 100644 GIT binary patch literal 115208 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 hItAtLCS6AVb-QV~Awz{{=WgXW#$; literal 47184 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 j1wCANtX}itzv{n=pESQSwO #include #include +#include "router/router.hpp" /* #include */ /* #include */ /* #include */ /* #include */ +#define SPACE 1 + short int connected[MAXLINE]={0}; //if line connected:2, if one end:1, otherwize:0 short int board_beta[MAXSIZE][MAXSIZE]; //big board data //edge:1~MAXLINE, line:-1~-MAXLINE, none:0, wall:SHRT_MIN short int rank[MAXBLOCK+1]; short int done_block[MAXBLOCK+1]; +short int board_str[900]; +vector mino_order; void reset_board(void){ int i,j; @@ -91,31 +96,58 @@ int check_around(int x,int y){ return 0; } } +void del_mino(int mino){ + int x,y; + x=block_data[mino][0][0]; + y=block_data[mino][0][1]; + for(int i=1;i<5;i++){ + board_data[x+block_data[mino][i][0]][y+block_data[mino][i][1]]=0; + } + block_data[mino][0][0]=-1; + block_data[mino][0][1]=-1; +} + +int check_put_mino(int i,int x, int y){// check block#i can put on x,y + for(int j=1;j<5;j++){ + if(x+block_data[i][j][0]>19){ + return 0; + } + if(y+block_data[i][j][1]>19){ + return 0; + } + if(board_data[x+block_data[i][j][0]][y+block_data[i][j][1]]!=0){ + return 0; + } + if(check_around(x+block_data[i][j][0],y+block_data[i][j][1])){ + return 0; + } + } + return 1; +} + void data_mino(int i, int x,int y){ std::cout << "put mino "<< i << std::endl; for(int j=0;j<100;j++){ - for(int k=1;k<5;k++){ - if(board_data[x+block_data[i][k][0]][y+block_data[i][k][1]]!=0){ - break; - } - if(check_around(x+block_data[i][k][0],y+block_data[i][k][1])) break; - if(k==4){ - for(int l=1;l<5;l++){ - if(block_data[i][l][2]!=0){ - board_data[x+block_data[i][l][0]][y+block_data[i][l][1]]=block_data[i][l][2]; - }else{ - board_data[x+block_data[i][l][0]][y+block_data[i][l][1]]=-1; - } + if(check_put_mino(i,x,y)){ + for(int l=1;l<5;l++){ + if(l==2 && block_data[i][l][2]==-1){ + block_data[i][0][0]=x; + block_data[i][0][1]=y; + return; + } + if(block_data[i][l][2]!=0){ + board_data[x+block_data[i][l][0]][y+block_data[i][l][1]]=block_data[i][l][2]; + }else{ + board_data[x+block_data[i][l][0]][y+block_data[i][l][1]]=-1; } - block_data[i][0][0]=x; - block_data[i][0][1]=y; - return; } + block_data[i][0][0]=x; + block_data[i][0][1]=y; + return; } - - x+=(j%2); - y+=((j+1)%2); + x+=(j%2)*SPACE; + y+=((j+1)%2)*SPACE; if(x>W || y>H) return; } } @@ -229,7 +261,7 @@ void put_mino(){ itr=order_w.insert(itr,next); itr++; } - if(map_w[i]==0) continue; + if(map_w[i]==0|| map_w[i]==-1) continue; itr=order_w.insert(itr,map_w[i]); itr++; } @@ -354,7 +386,7 @@ void put_mino(){ itr=order_h.insert(itr,next); itr++; } - if(map_h[i]==0) continue; + if(map_h[i]==0|| map_h[i]==-1) continue; itr=order_h.insert(itr,map_h[i]); itr++; } @@ -363,8 +395,8 @@ void put_mino(){ } printf("\n"); done_block[next]=1; - x++; - if(x==1)break; + //x++; + //if(x==1)break; }//end of while ture for height printf("width is \n"); @@ -400,6 +432,7 @@ void put_mino(){ hight_c++; } data_mino(next_put,width_c,hight_c); + mino_order.push_back(next_put); }else{ for(int j=0;j1;j--){ + if(check_put_mino(next,j,mino_y)){ + mino_x=j; + }else{ + break; + } + } + }else{ + for(int j=mino_y-1;j>1;j--){ + if(check_put_mino(next,mino_x,j)){ + mino_y=j; + }else{ + break; + } + } + } + data_mino(next,mino_x,mino_y); + }*/ +} +void make_board_str(int size_x,int size_y){ + for(int y = 0; y < size_y; y++) { + for(int x = 0; x < size_x; x++) { + int idx = y * size_x + x; + board_str[idx] = board_data[y][x]; + } + } +} +void fix_to_board(int size_x, int size_y){ + for(int y = 0; y < size_y; y++) { + for(int x = 0; x < size_x; x++) { + int idx = y * size_x + x; + board_data[y][x] = board_str[idx]; + } + } } void line(){ - + make_board_str(20,20); + std::cout << lfsr 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 literal 0 HcmV?d00001 -- 2.22.0