From d8e859b67164039b8c968ca0e27b2c775a7c0d69 Mon Sep 17 00:00:00 2001 From: Lisa Liu Date: Fri, 22 Mar 2019 10:58:16 -0700 Subject: [PATCH] create standard xf_blas library --- LICENSE.txt | 218 +++++++ README.md | 19 + l1_primitive/include/hw/spmv.h | 730 ++++++++++++++++++++++ l1_primitive/include/hw/utility/utility.h | 331 ++++++++++ 4 files changed, 1298 insertions(+) create mode 100644 LICENSE.txt create mode 100644 README.md create mode 100755 l1_primitive/include/hw/spmv.h create mode 100755 l1_primitive/include/hw/utility/utility.h diff --git a/LICENSE.txt b/LICENSE.txt new file mode 100644 index 0000000000..c0357e01ca --- /dev/null +++ b/LICENSE.txt @@ -0,0 +1,218 @@ +Components: XF Database Library + + Apache License + Version 2.0, January 2004 + http://www.apache.org/licenses/ + +TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION + +1. Definitions. + + "License" shall mean the terms and conditions for use, reproduction, + and distribution as defined by Sections 1 through 9 of this document. + + "Licensor" shall mean the copyright owner or entity authorized by + the copyright owner that is granting the License. + + "Legal Entity" shall mean the union of the acting entity and all + other entities that control, are controlled by, or are under common + control with that entity. For the purposes of this definition, + "control" means (i) the power, direct or indirect, to cause the + direction or management of such entity, whether by contract or + otherwise, or (ii) ownership of fifty percent (50%) or more of the + outstanding shares, or (iii) beneficial ownership of such entity. + + "You" (or "Your") shall mean an individual or Legal Entity + exercising permissions granted by this License. + + "Source" form shall mean the preferred form for making modifications, + including but not limited to software source code, documentation + source, and configuration files. + + "Object" form shall mean any form resulting from mechanical + transformation or translation of a Source form, including but + not limited to compiled object code, generated documentation, + and conversions to other media types. + + "Work" shall mean the work of authorship, whether in Source or + Object form, made available under the License, as indicated by a + copyright notice that is included in or attached to the work + (an example is provided in the Appendix below). + + "Derivative Works" shall mean any work, whether in Source or Object + form, that is based on (or derived from) the Work and for which the + editorial revisions, annotations, elaborations, or other modifications + represent, as a whole, an original work of authorship. For the purposes + of this License, Derivative Works shall not include works that remain + separable from, or merely link (or bind by name) to the interfaces of, + the Work and Derivative Works thereof. + + "Contribution" shall mean any work of authorship, including + the original version of the Work and any modifications or additions + to that Work or Derivative Works thereof, that is intentionally + submitted to Licensor for inclusion in the Work by the copyright owner + or by an individual or Legal Entity authorized to submit on behalf of + the copyright owner. For the purposes of this definition, "submitted" + means any form of electronic, verbal, or written communication sent + to the Licensor or its representatives, including but not limited to + communication on electronic mailing lists, source code control systems, + and issue tracking systems that are managed by, or on behalf of, the + Licensor for the purpose of discussing and improving the Work, but + excluding communication that is conspicuously marked or otherwise + designated in writing by the copyright owner as "Not a Contribution." + + "Contributor" shall mean Licensor and any individual or Legal Entity + on behalf of whom a Contribution has been received by Licensor and + subsequently incorporated within the Work. + +2. Grant of Copyright License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + copyright license to reproduce, prepare Derivative Works of, + publicly display, publicly perform, sublicense, and distribute the + Work and such Derivative Works in Source or Object form. + +3. Grant of Patent License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + (except as stated in this section) patent license to make, have made, + use, offer to sell, sell, import, and otherwise transfer the Work, + where such license applies only to those patent claims licensable + by such Contributor that are necessarily infringed by their + Contribution(s) alone or by combination of their Contribution(s) + with the Work to which such Contribution(s) was submitted. If You + institute patent litigation against any entity (including a + cross-claim or counterclaim in a lawsuit) alleging that the Work + or a Contribution incorporated within the Work constitutes direct + or contributory patent infringement, then any patent licenses + granted to You under this License for that Work shall terminate + as of the date such litigation is filed. + +4. Redistribution. You may reproduce and distribute copies of the + Work or Derivative Works thereof in any medium, with or without + modifications, and in Source or Object form, provided that You + meet the following conditions: + + (a) You must give any other recipients of the Work or + Derivative Works a copy of this License; and + + (b) You must cause any modified files to carry prominent notices + stating that You changed the files; and + + (c) You must retain, in the Source form of any Derivative Works + that You distribute, all copyright, patent, trademark, and + attribution notices from the Source form of the Work, + excluding those notices that do not pertain to any part of + the Derivative Works; and + + (d) If the Work includes a "NOTICE" text file as part of its + distribution, then any Derivative Works that You distribute must + include a readable copy of the attribution notices contained + within such NOTICE file, excluding those notices that do not + pertain to any part of the Derivative Works, in at least one + of the following places: within a NOTICE text file distributed + as part of the Derivative Works; within the Source form or + documentation, if provided along with the Derivative Works; or, + within a display generated by the Derivative Works, if and + wherever such third-party notices normally appear. The contents + of the NOTICE file are for informational purposes only and + do not modify the License. You may add Your own attribution + notices within Derivative Works that You distribute, alongside + or as an addendum to the NOTICE text from the Work, provided + that such additional attribution notices cannot be construed + as modifying the License. + + You may add Your own copyright statement to Your modifications and + may provide additional or different license terms and conditions + for use, reproduction, or distribution of Your modifications, or + for any such Derivative Works as a whole, provided Your use, + reproduction, and distribution of the Work otherwise complies with + the conditions stated in this License. + +5. Submission of Contributions. Unless You explicitly state otherwise, + any Contribution intentionally submitted for inclusion in the Work + by You to the Licensor shall be under the terms and conditions of + this License, without any additional terms or conditions. + Notwithstanding the above, nothing herein shall supersede or modify + the terms of any separate license agreement you may have executed + with Licensor regarding such Contributions. + +6. Trademarks. This License does not grant permission to use the trade + names, trademarks, service marks, or product names of the Licensor, + except as required for reasonable and customary use in describing the + origin of the Work and reproducing the content of the NOTICE file. + +7. Disclaimer of Warranty. Unless required by applicable law or + agreed to in writing, Licensor provides the Work (and each + Contributor provides its Contributions) on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + implied, including, without limitation, any warranties or conditions + of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A + PARTICULAR PURPOSE. You are solely responsible for determining the + appropriateness of using or redistributing the Work and assume any + risks associated with Your exercise of permissions under this License. + +8. Limitation of Liability. In no event and under no legal theory, + whether in tort (including negligence), contract, or otherwise, + unless required by applicable law (such as deliberate and grossly + negligent acts) or agreed to in writing, shall any Contributor be + liable to You for damages, including any direct, indirect, special, + incidental, or consequential damages of any character arising as a + result of this License or out of the use or inability to use the + Work (including but not limited to damages for loss of goodwill, + work stoppage, computer failure or malfunction, or any and all + other commercial damages or losses), even if such Contributor + has been advised of the possibility of such damages. + +9. Accepting Warranty or Additional Liability. While redistributing + the Work or Derivative Works thereof, You may choose to offer, + and charge a fee for, acceptance of support, warranty, indemnity, + or other liability obligations and/or rights consistent with this + License. However, in accepting such obligations, You may act only + on Your own behalf and on Your sole responsibility, not on behalf + of any other Contributor, and only if You agree to indemnify, + defend, and hold each Contributor harmless for any liability + incurred by, or claims asserted against, such Contributor by reason + of your accepting any such warranty or additional liability. + +END OF TERMS AND CONDITIONS + +Copyright 2018 Xilinx Inc + + +------------------------------------------------------------ + + +Components: SDAccel Exmaples code in ext folder + +/********** +Copyright (c) 2018, Xilinx, Inc. +All rights reserved. + +Redistribution and use in source and binary forms, with or without modification, +are permitted provided that the following conditions are met: + +1. Redistributions of source code must retain the above copyright notice, +this list of conditions and the following disclaimer. + +2. Redistributions in binary form must reproduce the above copyright notice, +this list of conditions and the following disclaimer in the documentation +and/or other materials provided with the distribution. + +3. Neither the name of the copyright holder nor the names of its contributors +may be used to endorse or promote products derived from this software +without specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND +ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, +THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. +IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, +INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, +PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) +HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, +EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +**********/ + +Copyright 2018 Xilinx Inc + diff --git a/README.md b/README.md new file mode 100644 index 0000000000..1a6d966fe1 --- /dev/null +++ b/README.md @@ -0,0 +1,19 @@ +# XF BLAS Library + +XF BLAS Library is an SDx library for accelerating linear algebra functions. + +[Comprehensive documentation](https://pages.gitenterprise.xilinx.com/FaaSApps/gemx/guide/pyguide.html) + +Copyright 2019 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. diff --git a/l1_primitive/include/hw/spmv.h b/l1_primitive/include/hw/spmv.h new file mode 100755 index 0000000000..5c2fdf7548 --- /dev/null +++ b/l1_primitive/include/hw/spmv.h @@ -0,0 +1,730 @@ +/********** + * Copyright (c) 2017-2019, Xilinx, Inc. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, + * are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * + * 3. Neither the name of the copyright holder nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, + * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + * IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, + * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, + * EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * **********/ +/** + * @brief Sparse matrix vector multiply C = A * B + * + * $DateTime: 2019/03/05 09:20:31 $ + * $Author: Xilinx $ + */ + +#ifndef SPMV_H +#define SPMV_H + +#include "assert.h" +#include "hls_stream.h" +#include "utility.h" + +namespace xf { + namespace blas { +template < + typename t_DataType +> +class SpmA { + private: + t_DataType m_Val; + unsigned int m_Col; + unsigned int m_Row; + public: + SpmA() {} + SpmA(t_DataType p_Val, unsigned int p_Col, unsigned int p_Row) + : m_Val(p_Val), m_Col(p_Col), m_Row(p_Row) {} + t_DataType &getVal() { return m_Val;} + unsigned int &getCol() { return m_Col;} + unsigned int &getRow() { return m_Row;} +}; + +template < + typename t_DataType +> +class SpmC { + private: + t_DataType m_Val; + unsigned int m_Row; + public: + SpmC() {} + SpmC(t_DataType p_Val, unsigned int p_Row) + : m_Val(p_Val), m_Row(p_Row) {} + t_DataType &getVal() { return m_Val;} + unsigned int &getRow() { return m_Row;} +}; + +template < + typename t_DataType, + unsigned int t_MemWidth, // number of matrix elements in one mem access + unsigned int t_IndexWidth, // number of indices in one mem access, index type is always unsigned int + unsigned int t_MaxK, // maximum number of input vector elements + unsigned int t_MaxM, // maximum number of output vector elements + unsigned int t_MaxNnz // maximum number of Nnzs +> +class Spmv +{ + private: + static const unsigned int t_IdxWidthOverMemWidth = t_IndexWidth / t_MemWidth; + static const unsigned int t_AccWidth = 3; //width for accumulator + static const unsigned int t_FifoDepth = 2; + public: + typedef WideType DataWideType; + typedef hls::stream DataWideStreamType; + typedef WideType IdxWideType; + typedef hls::stream IdxWideStreamType; + + typedef SpmA SpmAtype; + typedef WideType SpmAwideType; + typedef hls::stream SpmAwideStreamType; + typedef hls::stream SpmAstreamType; + + typedef SpmC SpmCtype; + typedef WideType SpmCwideType; + typedef hls::stream SpmCwideStreamType; + typedef hls::stream SpmCstreamType; + + typedef WideType AccDataType; + typedef SpmC SpmCaccType; + typedef hls::stream SpmCaccStreamType; + + typedef hls::stream ControlStreamType; + + private: + void + readA ( + t_DataType p_A[t_MaxNnz], + unsigned int p_NnzWords, + DataWideStreamType &p_ValStr){ + for (unsigned int i=0; i l_activity(true); + #pragma HLS array_partition variable=l_activity COMPLETE + LOOP_XCM_WHILE:while (!l_exit) { + #pragma HLS PIPELINE + if (l_preDone && !l_activity.Or()) { + l_exit = true; + } + bool l_unused; + if (p_CtrIn.read_nb(l_unused)) { + l_preDone = true; + } + l_activity.Reset(); + + LOOP_XCM_BANK_MERGE:for (int b = 0; b < t_MemWidth; ++b) { + #pragma HLS UNROLL + unsigned int l_idx = 0; + LOOP_XCM_IDX:for (int bb = 0; bb < t_MemWidth; ++bb) { + #pragma HLS UNROLL + unsigned int l_bank = (bb + b ) % t_MemWidth; + if (!p_StrIn[l_bank][b].empty()) { + l_idx = l_bank; + break; + } + } + + SpmAtype l_val; + if (p_StrIn[l_idx][b].read_nb(l_val)) { + p_StrOut[b].write(l_val); + l_activity[b] = true; + } + } + } + LOOP_XCM_SEND_EXIT:for (int b = 0; b < t_MemWidth; ++b) { + #pragma HLS UNROLL + p_CtrOut[b].write(true); + } + } + void + colUnit ( + t_DataType p_Vin[t_MaxK], + SpmAstreamType p_StrIn[t_MemWidth], + ControlStreamType p_CtrIn[t_MemWidth], + SpmCstreamType p_StrOut[t_MemWidth], + ControlStreamType p_CtrOut[t_MemWidth]){ + SpmAtype l_val; + bool l_exit = false; + BoolArr l_preDone(false); + BoolArr l_activity(true); + LOOP_CU_WHILE:while (!l_exit) { + #pragma HLS PIPELINE + if (l_preDone.And() && (!l_activity.Or())) { + l_exit = true; + } + LOOP_CU_CALC:for(unsigned int b=0; b l_activity(true); + BoolArr l_preActive(true); + #pragma HLS array_partition variable=l_activity COMPLETE + #pragma HLS array_partition variable=l_preActive COMPLETE + LOOP_XRS_WHILE:while (!l_exit) { + #pragma HLS PIPELINE + if (!l_preActive.Or() && !l_activity.Or()) { + l_exit = true; + } + l_activity.Reset(); + LOOP_XRS_W:for (int w = 0; w < t_MemWidth; ++w) { + #pragma HLS UNROLL + SpmCtype l_val; + if (p_StrIn[w].read_nb(l_val)) { + unsigned int l_rowBank = l_val.getRow() % t_MemWidth; + p_StrOut[w][l_rowBank].write(l_val); + l_activity[w] = true; + } + + bool l_unused; + if (p_CtrIn[w].read_nb(l_unused)) { + l_preActive[w] = false; + } + } + } + p_CtrOut.write(true); + } + void + xBarRowMerge ( + SpmCstreamType p_StrIn[t_MemWidth][t_MemWidth], + ControlStreamType &p_CtrIn, + SpmCstreamType p_StrOut[t_MemWidth], + ControlStreamType p_CtrOut[t_MemWidth]) { + bool l_exit = false, l_preDone = false; + BoolArr l_activity(true); + LOOP_XRM_WHILE:while (!l_exit) { + #pragma HLS PIPELINE + if (l_preDone && !l_activity.Or()) { + l_exit = true; + } + bool l_unused; + if (p_CtrIn.read_nb(l_unused)) { + l_preDone = true; + } + l_activity.Reset(); + LOOP_XRM_BANK_MERGE:for (int b = 0; b < t_MemWidth; ++b) { + #pragma HLS UNROLL + unsigned int l_idx = 0; + LOOP_XRM_IDX:for (int bb = 0; bb < t_MemWidth; ++bb) { + #pragma HLS UNROLL + unsigned int l_bank = (bb + b ) % t_MemWidth; + if (!p_StrIn[l_bank][b].empty()) { + l_idx = l_bank; + break; + } + } + SpmCtype l_val; + if (p_StrIn[l_idx][b].read_nb(l_val)) { + p_StrOut[b].write(l_val); + l_activity[b] = true; + } + } + } + LOOP_XRM_SEND_EXIT:for (int b = 0; b < t_MemWidth; ++b) { + #pragma HLS UNROLL + p_CtrOut[b].write(true); + } + } + void + rowUnit ( + SpmCstreamType &p_StrIn, + ControlStreamType &p_CtrIn, + SpmCaccStreamType &p_StrOut, + ControlStreamType &p_CtrOut, + unsigned int t_BankId) { + SpmCtype l_val(0, t_BankId); + unsigned int l_curRow = t_BankId; + AccDataType l_accVal(0); + #pragma HLS ARRAY_PARTITION variable=l_accVal dim=0 complete + uint8_t l_count=0; + + bool l_exit = false; + bool l_preDone = false; + bool l_activity = true; + LOOP_RU_WHILE:while (!l_exit) { + #pragma HLS PIPELINE + if (l_preDone && !l_activity) { + l_exit = true; + } + bool l_unused = false; + if (p_CtrIn.read_nb(l_unused)) { + l_preDone = true; + } + l_activity = false; + + if (p_StrIn.read_nb(l_val)) { + if ((l_val.getRow() != l_curRow) || (l_count == (t_AccWidth-1))) { + SpmCaccType l_acc(l_accVal, l_curRow); + p_StrOut.write(l_acc); + l_curRow = l_val.getRow(); + l_accVal[0] = l_val.getVal(); + for (unsigned int i=1; i l_cArr; + #pragma HLS ARRAY_PARTITION variable=l_cArr dim=1 complete + + bool l_exit = false; + bool l_preDone = false; + bool l_activity = true; + LOOP_REU_WHILE:while (!l_exit) { + #pragma HLS PIPELINE + if (l_preDone && !l_activity) { + l_exit = true; + } + bool l_unused = false; + if (p_CtrIn.read_nb(l_unused)) { + l_preDone = true; + } + l_activity = false; + + if (p_StrIn.read_nb(l_val)) { + l_accVal = l_val.getVal(); + l_accRow = l_val.getRow(); + for (unsigned int i=0; i l_preDone(false); + BoolArr l_activity(true); + LOOP_AU_WHILE:while (!l_exit) { + #pragma HLS PIPELINE + if (l_preDone.And() && !l_activity.Or()) { + l_exit = true; + } + for (unsigned int b=0; b l_preDone(false); + BoolArr l_activity(true); + LOOP_AU_WHILE:while (!l_exit) { + #pragma HLS PIPELINE + if (l_preDone.And() && !l_activity.Or()) { + l_exit = true; + } + for (unsigned int b=0; b +#include +#include +#include +#include "ap_int.h" +#include "ap_shift_reg.h" + +// Helper macros for renaming kernel +#define PASTER(x,y) x ## y +#define EVALUATOR(x,y) PASTER(x,y) + + +#define FLOAT_WIDTH 7 +#define CMP_WIDTH 11 + +constexpr size_t mylog2(size_t n) { + return ( (n<2) ? 0 : 1+mylog2(n/2)); +} + +template +class WideType { + private: + T m_Val[t_Width]; + static const unsigned int t_4k = 4096; + public: + typedef T DataType; + static const unsigned int t_WidthS = t_Width; + static const unsigned int t_per4k = t_4k / sizeof(T) / t_Width; + public: + T &getVal(unsigned int i) {return(m_Val[i]);} + T &operator[](unsigned int p_Idx) {return(m_Val[p_Idx]);} + T *getValAddr() {return(&m_Val[0]);} + WideType() {} + WideType(T p_initScalar) { + #pragma HLS inline self + for(int i = 0; i < t_Width; ++i) { + #pragma HLS UNROLL + getVal(i) = p_initScalar; + } + } + T + shift(T p_ValIn) { + #pragma HLS inline self + #pragma HLS data_pack variable=p_ValIn + T l_valOut = m_Val[t_Width-1]; + WIDE_TYPE_SHIFT:for(int i = t_Width - 1; i > 0; --i) { + T l_val = m_Val[i - 1]; + #pragma HLS data_pack variable=l_val + m_Val[i] = l_val; + } + m_Val[0] = p_ValIn; + return(l_valOut); + } + T + shift() { + #pragma HLS inline self + T l_valOut = m_Val[t_Width-1]; + WIDE_TYPE_SHIFT:for(int i = t_Width - 1; i > 0; --i) { + T l_val = m_Val[i - 1]; + #pragma HLS data_pack variable=l_val + m_Val[i] = l_val; + } + return(l_valOut); + } + T + unshift() { + #pragma HLS inline self + T l_valOut = m_Val[0]; + WIDE_TYPE_SHIFT:for(int i = 0; i < t_Width - 1; ++i) { + T l_val = m_Val[i + 1]; + #pragma HLS data_pack variable=l_val + m_Val[i] = l_val; + } + return(l_valOut); + } + static const WideType zero() { + WideType l_zero; + #pragma HLS data_pack variable=l_zero + for(int i = 0; i < t_Width; ++i) { + l_zero[i] = 0; + } + return(l_zero); + } + static + unsigned int + per4k() { + return(t_per4k); + } + void + print(std::ostream& os) { + for(int i = 0; i < t_Width; ++i) { + os << std::setw(FLOAT_WIDTH) << getVal(i) << " "; + } + } + +}; + +template +std::ostream& operator<<(std::ostream& os, WideType& p_Val) { + p_Val.print(os); + return(os); +} + + +template < + typename t_FloatType, + unsigned int t_MemWidth, // In t_FloatType + unsigned int t_MemWidthBits // In bits; both must be defined and be consistent + > +class MemUtil +{ + private: + public: + typedef WideType MemWideType; +}; +///////////////////////// Control and helper types ///////////////////////// + +template +T +hlsReg(T p_In) +{ + #pragma HLS INLINE self off + #pragma HLS INTERFACE ap_none port=return register + if (t_NumCycles == 1) { + return p_In; + } else { + return hlsReg (p_In); + } +} + +template +T +hlsReg(T p_In) +{ + return hlsReg (p_In); +} + +template +class BoolArr { + private: + bool m_Val[W]; + public: + BoolArr(){} + BoolArr(bool p_Init) { + #pragma HLS inline self + for(unsigned int i = 0; i < W; ++i) { + #pragma HLS UNROLL + m_Val[i] = p_Init; + } + } + bool & operator[](unsigned int p_Idx) { + #pragma HLS inline self + return m_Val[p_Idx]; + } + bool And() { + #pragma HLS inline self + bool l_ret = true; + for(unsigned int i = 0; i < W; ++i) { + #pragma HLS UNROLL + #pragma HLS ARRAY_PARTITION variable=m_Val COMPLETE + l_ret = l_ret && m_Val[i]; + } + return(l_ret); + } + bool Or() { + #pragma HLS inline self + bool l_ret = false; + for(unsigned int i = 0; i < W; ++i) { + #pragma HLS UNROLL + #pragma HLS ARRAY_PARTITION variable=m_Val COMPLETE + l_ret = l_ret || m_Val[i]; + } + return(l_ret); + } + void Reset() { + #pragma HLS inline self + for(unsigned int i = 0; i < W; ++i) { + #pragma HLS UNROLL + #pragma HLS ARRAY_PARTITION variable=m_Val COMPLETE + m_Val[i] = false; + } + } +}; + +template +bool +streamsAreEmpty(S p_Sin[W]) { + #pragma HLS inline self + bool l_allEmpty = true; + LOOP_S_IDX:for (int w = 0; w < W; ++w) { + #pragma HLS UNROLL + l_allEmpty = l_allEmpty && p_Sin[w].empty(); + } + return(l_allEmpty); +} + +// Bit converter +template +class BitConv { + public: + static const unsigned int t_SizeOf = sizeof(T); + static const unsigned int t_NumBits = 8 * sizeof(T); + typedef ap_uint BitsType; + public: + BitsType + toBits(T p_Val) { + return p_Val; + } + T + toType(BitsType p_Val) { + return p_Val; + } + }; + +template<> +inline +BitConv::BitsType +BitConv::toBits(float p_Val) { + union { + float f; + unsigned int i; + } u; + u.f = p_Val; + return(u.i); +} + +template<> +inline +float +BitConv::toType(BitConv::BitsType p_Val) { + union { + float f; + unsigned int i; + } u; + u.i = p_Val; + return(u.f); +} + +template<> +inline +BitConv::BitsType +BitConv::toBits(double p_Val) { + union { + double f; + int64_t i; + } u; + u.f = p_Val; + return(u.i); +} + +template<> +inline +double +BitConv::toType(BitConv::BitsType p_Val) { + union { + double f; + int64_t i; + } u; + u.i = p_Val; + return(u.f); +} + +// Type converter - for vectors of different lengths and types +template +class WideConv { + private: + static const unsigned int t_ws = TS::t_WidthS; + static const unsigned int t_wd = TD::t_WidthS; + typedef BitConv ConvSType; + typedef BitConv ConvDType; + static const unsigned int t_bs = ConvSType::t_NumBits; + static const unsigned int t_bd = ConvDType::t_NumBits; + static const unsigned int l_numBits = t_ws * t_bs; + private: + ap_uint l_bits; + public: + inline + TD + convert(TS p_Src) { + TD l_dst; + ConvSType l_convS; + assert(t_wd * t_bd == l_numBits); + for(int ws = 0; ws < t_ws; ++ws) { + l_bits.range(t_bs * (ws+1) - 1, t_bs * ws) = l_convS.toBits(p_Src[ws]); + } + ConvDType l_convD; + for(int wd = 0; wd < t_wd; ++wd) { + l_dst[wd] = l_convD.toType(l_bits.range(t_bd * (wd+1) - 1, t_bd * wd)); + } + + return(l_dst); + } +}; + +#endif