├── LICENSE ├── README.md └── WalkThroughs └── EdgeDetect └── src ├── EdgeDetect_Algorithm.h ├── EdgeDetect_BitAccurate.h ├── EdgeDetect_BitAccurate_tb.cpp ├── EdgeDetect_CircularBuf.h ├── EdgeDetect_CircularBuf.tcl ├── EdgeDetect_CircularBuf_power.tcl ├── EdgeDetect_CircularBuf_tb.cpp ├── EdgeDetect_Hierarchy.h ├── EdgeDetect_Hierarchy.tcl ├── EdgeDetect_Hierarchy_tb.cpp ├── EdgeDetect_MemoryArch.h ├── EdgeDetect_MemoryArch.tcl ├── EdgeDetect_MemoryArch_tb.cpp ├── EdgeDetect_SinglePort.h ├── EdgeDetect_SinglePort.tcl ├── EdgeDetect_SinglePort_Programable.h ├── EdgeDetect_SinglePort_Programable.tcl ├── EdgeDetect_SinglePort_Programable_tb.cpp ├── EdgeDetect_SinglePort_tb.cpp ├── EdgeDetect_Synthesizable.h ├── EdgeDetect_Synthesizable.tcl ├── EdgeDetect_Synthesizable_tb.cpp ├── Makefile ├── README.txt ├── edge_defs.h ├── image └── people_gray.bmp ├── nangate-45nm_mem.lib ├── ram_1k_16_sp.h ├── ram_1k_16_sp.tcl ├── ram_1k_16_sp.v ├── ram_1k_16_sp.vhd └── ram_1k_16_sp_trans_rsc.h /LICENSE: -------------------------------------------------------------------------------- 1 | Apache License 2 | Version 2.0, January 2004 3 | http://www.apache.org/licenses/ 4 | 5 | TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION 6 | 7 | 1. Definitions. 8 | 9 | "License" shall mean the terms and conditions for use, reproduction, 10 | and distribution as defined by Sections 1 through 9 of this document. 11 | 12 | "Licensor" shall mean the copyright owner or entity authorized by 13 | the copyright owner that is granting the License. 14 | 15 | "Legal Entity" shall mean the union of the acting entity and all 16 | other entities that control, are controlled by, or are under common 17 | control with that entity. For the purposes of this definition, 18 | "control" means (i) the power, direct or indirect, to cause the 19 | direction or management of such entity, whether by contract or 20 | otherwise, or (ii) ownership of fifty percent (50%) or more of the 21 | outstanding shares, or (iii) beneficial ownership of such entity. 22 | 23 | "You" (or "Your") shall mean an individual or Legal Entity 24 | exercising permissions granted by this License. 25 | 26 | "Source" form shall mean the preferred form for making modifications, 27 | including but not limited to software source code, documentation 28 | source, and configuration files. 29 | 30 | "Object" form shall mean any form resulting from mechanical 31 | transformation or translation of a Source form, including but 32 | not limited to compiled object code, generated documentation, 33 | and conversions to other media types. 34 | 35 | "Work" shall mean the work of authorship, whether in Source or 36 | Object form, made available under the License, as indicated by a 37 | copyright notice that is included in or attached to the work 38 | (an example is provided in the Appendix below). 39 | 40 | "Derivative Works" shall mean any work, whether in Source or Object 41 | form, that is based on (or derived from) the Work and for which the 42 | editorial revisions, annotations, elaborations, or other modifications 43 | represent, as a whole, an original work of authorship. For the purposes 44 | of this License, Derivative Works shall not include works that remain 45 | separable from, or merely link (or bind by name) to the interfaces of, 46 | the Work and Derivative Works thereof. 47 | 48 | "Contribution" shall mean any work of authorship, including 49 | the original version of the Work and any modifications or additions 50 | to that Work or Derivative Works thereof, that is intentionally 51 | submitted to Licensor for inclusion in the Work by the copyright owner 52 | or by an individual or Legal Entity authorized to submit on behalf of 53 | the copyright owner. For the purposes of this definition, "submitted" 54 | means any form of electronic, verbal, or written communication sent 55 | to the Licensor or its representatives, including but not limited to 56 | communication on electronic mailing lists, source code control systems, 57 | and issue tracking systems that are managed by, or on behalf of, the 58 | Licensor for the purpose of discussing and improving the Work, but 59 | excluding communication that is conspicuously marked or otherwise 60 | designated in writing by the copyright owner as "Not a Contribution." 61 | 62 | "Contributor" shall mean Licensor and any individual or Legal Entity 63 | on behalf of whom a Contribution has been received by Licensor and 64 | subsequently incorporated within the Work. 65 | 66 | 2. Grant of Copyright License. Subject to the terms and conditions of 67 | this License, each Contributor hereby grants to You a perpetual, 68 | worldwide, non-exclusive, no-charge, royalty-free, irrevocable 69 | copyright license to reproduce, prepare Derivative Works of, 70 | publicly display, publicly perform, sublicense, and distribute the 71 | Work and such Derivative Works in Source or Object form. 72 | 73 | 3. Grant of Patent License. Subject to the terms and conditions of 74 | this License, each Contributor hereby grants to You a perpetual, 75 | worldwide, non-exclusive, no-charge, royalty-free, irrevocable 76 | (except as stated in this section) patent license to make, have made, 77 | use, offer to sell, sell, import, and otherwise transfer the Work, 78 | where such license applies only to those patent claims licensable 79 | by such Contributor that are necessarily infringed by their 80 | Contribution(s) alone or by combination of their Contribution(s) 81 | with the Work to which such Contribution(s) was submitted. If You 82 | institute patent litigation against any entity (including a 83 | cross-claim or counterclaim in a lawsuit) alleging that the Work 84 | or a Contribution incorporated within the Work constitutes direct 85 | or contributory patent infringement, then any patent licenses 86 | granted to You under this License for that Work shall terminate 87 | as of the date such litigation is filed. 88 | 89 | 4. Redistribution. You may reproduce and distribute copies of the 90 | Work or Derivative Works thereof in any medium, with or without 91 | modifications, and in Source or Object form, provided that You 92 | meet the following conditions: 93 | 94 | (a) You must give any other recipients of the Work or 95 | Derivative Works a copy of this License; and 96 | 97 | (b) You must cause any modified files to carry prominent notices 98 | stating that You changed the files; and 99 | 100 | (c) You must retain, in the Source form of any Derivative Works 101 | that You distribute, all copyright, patent, trademark, and 102 | attribution notices from the Source form of the Work, 103 | excluding those notices that do not pertain to any part of 104 | the Derivative Works; and 105 | 106 | (d) If the Work includes a "NOTICE" text file as part of its 107 | distribution, then any Derivative Works that You distribute must 108 | include a readable copy of the attribution notices contained 109 | within such NOTICE file, excluding those notices that do not 110 | pertain to any part of the Derivative Works, in at least one 111 | of the following places: within a NOTICE text file distributed 112 | as part of the Derivative Works; within the Source form or 113 | documentation, if provided along with the Derivative Works; or, 114 | within a display generated by the Derivative Works, if and 115 | wherever such third-party notices normally appear. The contents 116 | of the NOTICE file are for informational purposes only and 117 | do not modify the License. You may add Your own attribution 118 | notices within Derivative Works that You distribute, alongside 119 | or as an addendum to the NOTICE text from the Work, provided 120 | that such additional attribution notices cannot be construed 121 | as modifying the License. 122 | 123 | You may add Your own copyright statement to Your modifications and 124 | may provide additional or different license terms and conditions 125 | for use, reproduction, or distribution of Your modifications, or 126 | for any such Derivative Works as a whole, provided Your use, 127 | reproduction, and distribution of the Work otherwise complies with 128 | the conditions stated in this License. 129 | 130 | 5. Submission of Contributions. Unless You explicitly state otherwise, 131 | any Contribution intentionally submitted for inclusion in the Work 132 | by You to the Licensor shall be under the terms and conditions of 133 | this License, without any additional terms or conditions. 134 | Notwithstanding the above, nothing herein shall supersede or modify 135 | the terms of any separate license agreement you may have executed 136 | with Licensor regarding such Contributions. 137 | 138 | 6. Trademarks. This License does not grant permission to use the trade 139 | names, trademarks, service marks, or product names of the Licensor, 140 | except as required for reasonable and customary use in describing the 141 | origin of the Work and reproducing the content of the NOTICE file. 142 | 143 | 7. Disclaimer of Warranty. Unless required by applicable law or 144 | agreed to in writing, Licensor provides the Work (and each 145 | Contributor provides its Contributions) on an "AS IS" BASIS, 146 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or 147 | implied, including, without limitation, any warranties or conditions 148 | of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A 149 | PARTICULAR PURPOSE. You are solely responsible for determining the 150 | appropriateness of using or redistributing the Work and assume any 151 | risks associated with Your exercise of permissions under this License. 152 | 153 | 8. Limitation of Liability. In no event and under no legal theory, 154 | whether in tort (including negligence), contract, or otherwise, 155 | unless required by applicable law (such as deliberate and grossly 156 | negligent acts) or agreed to in writing, shall any Contributor be 157 | liable to You for damages, including any direct, indirect, special, 158 | incidental, or consequential damages of any character arising as a 159 | result of this License or out of the use or inability to use the 160 | Work (including but not limited to damages for loss of goodwill, 161 | work stoppage, computer failure or malfunction, or any and all 162 | other commercial damages or losses), even if such Contributor 163 | has been advised of the possibility of such damages. 164 | 165 | 9. Accepting Warranty or Additional Liability. While redistributing 166 | the Work or Derivative Works thereof, You may choose to offer, 167 | and charge a fee for, acceptance of support, warranty, indemnity, 168 | or other liability obligations and/or rights consistent with this 169 | License. However, in accepting such obligations, You may act only 170 | on Your own behalf and on Your sole responsibility, not on behalf 171 | of any other Contributor, and only if You agree to indemnify, 172 | defend, and hold each Contributor harmless for any liability 173 | incurred by, or claims asserted against, such Contributor by reason 174 | of your accepting any such warranty or additional liability. 175 | 176 | END OF TERMS AND CONDITIONS 177 | 178 | APPENDIX: How to apply the Apache License to your work. 179 | 180 | To apply the Apache License to your work, attach the following 181 | boilerplate notice, with the fields enclosed by brackets "[]" 182 | replaced with your own identifying information. (Don't include 183 | the brackets!) The text should be enclosed in the appropriate 184 | comment syntax for the file format. We also recommend that a 185 | file or class name and description of purpose be included on the 186 | same "printed page" as the copyright notice for easier 187 | identification within third-party archives. 188 | 189 | Copyright [yyyy] [name of copyright owner] 190 | 191 | Licensed under the Apache License, Version 2.0 (the "License"); 192 | you may not use this file except in compliance with the License. 193 | You may obtain a copy of the License at 194 | 195 | http://www.apache.org/licenses/LICENSE-2.0 196 | 197 | Unless required by applicable law or agreed to in writing, software 198 | distributed under the License is distributed on an "AS IS" BASIS, 199 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 200 | See the License for the specific language governing permissions and 201 | limitations under the License. 202 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # hls_tutorials 2 | Tutorials on HLS Design.
3 | Discover all the tutorial videos on our YouTube Channel: Catapult High-Level Synthesis 4 | -------------------------------------------------------------------------------- /WalkThroughs/EdgeDetect/src/EdgeDetect_Algorithm.h: -------------------------------------------------------------------------------- 1 | /************************************************************************** 2 | * * 3 | * Edge Detect Design Walkthrough for HLS * 4 | * * 5 | * Software Version: 1.0 * 6 | * * 7 | * Release Date : Tue Jan 14 15:40:43 PST 2020 * 8 | * Release Type : Production Release * 9 | * Release Build : 1.0.0 * 10 | * * 11 | * Copyright 2020, Mentor Graphics Corporation, * 12 | * * 13 | * All Rights Reserved. * 14 | * 15 | ************************************************************************** 16 | * Licensed under the Apache License, Version 2.0 (the "License"); * 17 | * you may not use this file except in compliance with the License. * 18 | * You may obtain a copy of the License at * 19 | * * 20 | * http://www.apache.org/licenses/LICENSE-2.0 * 21 | * * 22 | * Unless required by applicable law or agreed to in writing, software * 23 | * distributed under the License is distributed on an "AS IS" BASIS, * 24 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or * 25 | * implied. * 26 | * See the License for the specific language governing permissions and * 27 | * limitations under the License. * 28 | ************************************************************************** 29 | * * 30 | * The most recent version of this package is available at github. * 31 | * * 32 | *************************************************************************/ 33 | #ifndef _INCLUDED_EDGEDETECT_ALGORITHM_H_ 34 | #define _INCLUDED_EDGEDETECT_ALGORITHM_H_ 35 | 36 | // Revision History 37 | // Rev 1 - Coding of edge detection algorithm in C++ 38 | 39 | #include 40 | #include 41 | // Include constant kernel definition 42 | #include "edge_defs.h" 43 | 44 | class EdgeDetect_Algorithm 45 | { 46 | // Define some "constants" for use in algorithm 47 | enum { 48 | imageWidth = 1296, 49 | imageHeight = 864 50 | }; 51 | 52 | public: 53 | // Constructor 54 | EdgeDetect_Algorithm() {} 55 | 56 | //-------------------------------------------------------------------------- 57 | // Function: run 58 | // Top interface for data in/out of class. Combines vertical and 59 | // horizontal derivative and magnitude/angle computation. 60 | void run(unsigned char *dat_in, // image data (streamed in by pixel) 61 | double *magn, // magnitude output 62 | double *angle) // angle output 63 | { 64 | // allocate buffers for image data 65 | double *dy = (double *)malloc(imageHeight*imageWidth*sizeof(double)); 66 | double *dx = (double *)malloc(imageHeight*imageWidth*sizeof(double)); 67 | 68 | verticalDerivative(dat_in, dy); 69 | horizontalDerivative(dat_in, dx); 70 | magnitudeAngle(dx, dy, magn, angle); 71 | 72 | free(dy); 73 | free(dx); 74 | } 75 | 76 | //-------------------------------------------------------------------------- 77 | // Function: verticalDerivative 78 | // Compute the vertical derivative on the input data 79 | void verticalDerivative(unsigned char *dat_in, 80 | double *dy) 81 | { 82 | for (int y = 0; y < imageHeight; y++) { 83 | for (int x = 0; x < imageWidth; x++) { 84 | *(dy + y * imageWidth + x) = 85 | dat_in[clip(y - 1, imageHeight-1) * imageWidth + x] * kernel[0] + 86 | dat_in[y * imageWidth + x] * kernel[1] + 87 | dat_in[clip(y + 1, imageHeight-1) * imageWidth + x] * kernel[2]; 88 | } 89 | } 90 | } 91 | 92 | //-------------------------------------------------------------------------- 93 | // Function: horizontalDerivative 94 | // Compute the horizontal derivative on the input data 95 | void horizontalDerivative(unsigned char *dat_in, 96 | double *dx) 97 | { 98 | for (int y = 0; y < imageHeight; y++) { 99 | for (int x = 0; x < imageWidth; x++) { 100 | *(dx + y * imageWidth + x) = 101 | dat_in[y * imageWidth + clip(x - 1, imageWidth-1)] * kernel[0] + 102 | dat_in[y * imageWidth + x] * kernel[1] + 103 | dat_in[y * imageWidth + clip(x + 1, imageWidth-1)] * kernel[2]; 104 | } 105 | } 106 | } 107 | 108 | //-------------------------------------------------------------------------- 109 | // Function: magnitudeAngle 110 | // Compute the magnitute and angle based on the horizontal and vertical 111 | // derivative results 112 | void magnitudeAngle(double *dx, 113 | double *dy, 114 | double *magn, 115 | double *angle) 116 | { 117 | double dx_sq; 118 | double dy_sq; 119 | double sum; 120 | for (int y = 0; y < imageHeight; y++) { 121 | for (int x = 0; x < imageWidth; x++) { 122 | dx_sq = *(dx + y * imageWidth + x) * *(dx + y * imageWidth + x); 123 | dy_sq = *(dy + y * imageWidth + x) * *(dy + y * imageWidth + x); 124 | sum = dx_sq + dy_sq; 125 | *(magn + y * imageWidth + x) = sqrt(sum); 126 | *(angle + y * imageWidth + x) = atan2(dy[y * imageWidth + x], dx[y * imageWidth + x]); 127 | } 128 | } 129 | } 130 | 131 | private: // Helper functions 132 | 133 | //-------------------------------------------------------------------------- 134 | // Function: clip 135 | // Perform boundary processing by "adjusting" the index value to "clip" 136 | // at either end 137 | int clip(int i, int bound) { 138 | if (i < 0) { 139 | return 0; // clip to the top/left value 140 | } else if (i >= bound) { 141 | return bound; // clip to the bottom/right value 142 | } else { 143 | return i; // return all others untouched 144 | } 145 | } 146 | 147 | }; 148 | 149 | #endif 150 | 151 | -------------------------------------------------------------------------------- /WalkThroughs/EdgeDetect/src/EdgeDetect_BitAccurate.h: -------------------------------------------------------------------------------- 1 | /************************************************************************** 2 | * * 3 | * Edge Detect Design Walkthrough for HLS * 4 | * * 5 | * Software Version: 1.0 * 6 | * * 7 | * Release Date : Tue Jan 14 15:40:43 PST 2020 * 8 | * Release Type : Production Release * 9 | * Release Build : 1.0.0 * 10 | * * 11 | * Copyright 2020, Mentor Graphics Corporation, * 12 | * * 13 | * All Rights Reserved. * 14 | * 15 | ************************************************************************** 16 | * Licensed under the Apache License, Version 2.0 (the "License"); * 17 | * you may not use this file except in compliance with the License. * 18 | * You may obtain a copy of the License at * 19 | * * 20 | * http://www.apache.org/licenses/LICENSE-2.0 * 21 | * * 22 | * Unless required by applicable law or agreed to in writing, software * 23 | * distributed under the License is distributed on an "AS IS" BASIS, * 24 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or * 25 | * implied. * 26 | * See the License for the specific language governing permissions and * 27 | * limitations under the License. * 28 | ************************************************************************** 29 | * * 30 | * The most recent version of this package is available at github. * 31 | * * 32 | *************************************************************************/ 33 | #ifndef _INCLUDED_EDGEDETECT_BIT_ACCURATE_H_ 34 | #define _INCLUDED_EDGEDETECT_BIT_ACCURATE_H_ 35 | 36 | // Revision History 37 | // Rev 1 - Coding of edge detection algorithm in C++ 38 | // Rev 2 - Converted to using bit-accurate data types 39 | // Calculated bit growth for internal variables 40 | // Quantized angle values for 5 fractional bits -pi to pi 41 | 42 | #include 43 | #include 44 | 45 | // Include constant kernel definition 46 | #include "edge_defs.h" 47 | 48 | class EdgeDetect_BitAccurate 49 | { 50 | // Define some bit-accurate types to use in this model 51 | typedef uint8 pixelType; // input pixel is 0-255 52 | typedef int9 gradType; // Gradient is max range -255 to 255 53 | typedef uint18 sqType; // Result of 9-bit x 9-bit 54 | typedef ac_fixed<19,19,false> sumType; // Result of 18-bit + 18-bit fixed pt integer for squareroot 55 | typedef uint9 magType; // 9-bit unsigned magnitute result 56 | typedef ac_fixed<8,3,true> angType; // 3 integer bit, 5 fractional bits for quantized angle -pi to pi 57 | 58 | // Define some "constants" for use in algorithm 59 | enum { 60 | imageWidth = 1296, 61 | imageHeight = 864 62 | }; 63 | 64 | public: 65 | // Constructor 66 | EdgeDetect_BitAccurate() {} 67 | 68 | //-------------------------------------------------------------------------- 69 | // Function: run 70 | // Top interface for data in/out of class. Combines vertical and 71 | // horizontal derivative and magnitude/angle computation. 72 | void run(pixelType *dat_in, // 8-bit unsigned for pixel data 73 | magType *magn, // 9-bit unsigned for magnitude output 74 | angType *angle) // 3-integer/5-fractional bits for quantized output 75 | { 76 | // allocate buffers for image data 77 | gradType *dy = (gradType *)malloc(imageHeight*imageWidth*sizeof(gradType)); 78 | gradType *dx = (gradType *)malloc(imageHeight*imageWidth*sizeof(gradType)); 79 | 80 | verticalDerivative(dat_in, dy); 81 | horizontalDerivative(dat_in, dx); 82 | magnitudeAngle(dx, dy, magn, angle); 83 | 84 | free(dy); 85 | free(dx); 86 | } 87 | 88 | //-------------------------------------------------------------------------- 89 | // Function: verticalDerivative 90 | // Compute the vertical derivative on the input data 91 | void verticalDerivative(pixelType *dat_in, 92 | gradType *dy) 93 | { 94 | for (int y = 0; y < imageHeight; y++) { 95 | for (int x = 0; x < imageWidth; x++) { 96 | *(dy + y * imageWidth + x) = 97 | dat_in[clip(y - 1, imageHeight-1) * imageWidth + x] * kernel[0] + 98 | dat_in[y * imageWidth + x] * kernel[1] + 99 | dat_in[clip(y + 1, imageHeight-1) * imageWidth + x] * kernel[2]; 100 | } 101 | } 102 | } 103 | 104 | //-------------------------------------------------------------------------- 105 | // Function: horizontalDerivative 106 | // Compute the horizontal derivative on the input data 107 | void horizontalDerivative(pixelType *dat_in, 108 | gradType *dx) 109 | { 110 | for (int y = 0; y < imageHeight; y++) { 111 | for (int x = 0; x < imageWidth; x++) { 112 | *(dx + y * imageWidth + x) = 113 | dat_in[y * imageWidth + clip(x - 1, imageWidth-1)] * kernel[0] + 114 | dat_in[y * imageWidth + x] * kernel[1] + 115 | dat_in[y * imageWidth + clip(x + 1, imageWidth-1)] * kernel[2]; 116 | } 117 | } 118 | } 119 | 120 | //-------------------------------------------------------------------------- 121 | // Function: magnitudeAngle 122 | // Compute the magnitute and angle based on the horizontal and vertical 123 | // derivative results 124 | void magnitudeAngle(gradType *dx, 125 | gradType *dy, 126 | magType *magn, 127 | angType *angle) 128 | { 129 | sqType dx_sq; 130 | sqType dy_sq; 131 | sumType sum; 132 | for (int y = 0; y < imageHeight; y++) { 133 | for (int x = 0; x < imageWidth; x++) { 134 | dx_sq = *(dx + y * imageWidth + x) * *(dx + y * imageWidth + x); 135 | dy_sq = *(dy + y * imageWidth + x) * *(dy + y * imageWidth + x); 136 | sum = dx_sq + dy_sq; 137 | *(magn + y * imageWidth + x) = sqrt(sum.to_double()); // Convert ac_fixed to double to call math.h sqrt() 138 | *(angle + y * imageWidth + x) = atan2(dy[y * imageWidth + x].to_int(), dx[y * imageWidth + x].to_int()); 139 | } 140 | } 141 | } 142 | 143 | private: // Helper functions 144 | 145 | //-------------------------------------------------------------------------- 146 | // Function: clip 147 | // Perform boundary processing by "adjusting" the index value to "clip" 148 | // at either end 149 | int clip(int i, int bound) { 150 | if (i < 0) { 151 | return 0; // clip to the top/left value 152 | } else if (i >= bound) { 153 | return bound; // clip to the bottom/right value 154 | } else { 155 | return i; // return all others untouched 156 | } 157 | } 158 | 159 | }; 160 | 161 | #endif 162 | 163 | -------------------------------------------------------------------------------- /WalkThroughs/EdgeDetect/src/EdgeDetect_BitAccurate_tb.cpp: -------------------------------------------------------------------------------- 1 | /************************************************************************** 2 | * * 3 | * Edge Detect Design Walkthrough for HLS * 4 | * * 5 | * Software Version: 1.0 * 6 | * * 7 | * Release Date : Tue Jan 14 15:40:43 PST 2020 * 8 | * Release Type : Production Release * 9 | * Release Build : 1.0.0 * 10 | * * 11 | * Copyright 2020, Mentor Graphics Corporation, * 12 | * * 13 | * All Rights Reserved. * 14 | * 15 | ************************************************************************** 16 | * Licensed under the Apache License, Version 2.0 (the "License"); * 17 | * you may not use this file except in compliance with the License. * 18 | * You may obtain a copy of the License at * 19 | * * 20 | * http://www.apache.org/licenses/LICENSE-2.0 * 21 | * * 22 | * Unless required by applicable law or agreed to in writing, software * 23 | * distributed under the License is distributed on an "AS IS" BASIS, * 24 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or * 25 | * implied. * 26 | * See the License for the specific language governing permissions and * 27 | * limitations under the License. * 28 | ************************************************************************** 29 | * * 30 | * The most recent version of this package is available at github. * 31 | * * 32 | *************************************************************************/ 33 | #include 34 | #include 35 | 36 | using namespace std; 37 | 38 | #include "EdgeDetect_Algorithm.h" 39 | #include "EdgeDetect_BitAccurate.h" 40 | 41 | #include "bmpUtil/bmp_io.hpp" 42 | #include 43 | #include 44 | #include 45 | #include 46 | #include 47 | 48 | CCS_MAIN(int argc, char *argv[]) 49 | { 50 | const int iW = 1296; 51 | const int iH = 864; 52 | EdgeDetect_Algorithm inst0; 53 | EdgeDetect_BitAccurate inst1; 54 | 55 | unsigned long int width = iW; 56 | long int height = iH; 57 | unsigned char *rarray = new unsigned char[iW*iH]; 58 | unsigned char *garray = new unsigned char[iW*iH]; 59 | unsigned char *barray = new unsigned char[iW*iH]; 60 | 61 | cout << "Loading Input File" << endl; 62 | 63 | if (argc < 3) { 64 | cout << "Usage: " << argv[0] << " " << endl; 65 | CCS_RETURN(-1); 66 | } 67 | 68 | std::string bmpIn(argv[1]); // input bitmap file 69 | std::string bmpAlg(argv[2]); // output bitmap (algorithm) 70 | std::string bmpBA(argv[3]); // output bitmap (bit-accurate) 71 | 72 | bmp_read((char*)bmpIn.c_str(), &width, &height, &rarray, &garray, &barray); 73 | assert(width==iW); 74 | assert(height==iH); 75 | 76 | #ifdef DEBUG 77 | std::string cmd; 78 | cmd = "display "; 79 | cmd.append(bmpIn.c_str()); 80 | std::cout << "Display input image file using command: " << cmd << endl; 81 | std::system(cmd.c_str()); 82 | #endif 83 | 84 | uint8 *dat_in = new uint8[iH*iW]; 85 | uint9 *magn = new uint9[iH*iW]; 86 | ac_fixed<8,3> *angle = new ac_fixed<8,3>[iH*iW];; 87 | unsigned char *dat_in_orig = new unsigned char[iH*iW];; 88 | double *magn_orig = new double[iH*iW]; 89 | double *angle_orig = new double[iH*iW]; 90 | 91 | unsigned cnt = 0; 92 | for (int y = 0; y < iH; y++) { 93 | for (int x = 0; x < iW; x++) { 94 | dat_in[cnt] = rarray[cnt]; // just using red component (pseudo monochrome) 95 | dat_in_orig[cnt] = rarray[cnt]; 96 | cnt++; 97 | } 98 | } 99 | 100 | cout << "Running" << endl; 101 | 102 | inst0.run(dat_in_orig,magn_orig,angle_orig); 103 | inst1.run(dat_in,magn,angle); 104 | 105 | cnt = 0; 106 | float sumErr = 0; 107 | float sumAngErr = 0; 108 | for (int y = 0; y < iH; y++) { 109 | for (int x = 0; x < iW; x++) { 110 | int hw = *(magn+cnt); 111 | int alg = (int)*(magn_orig+cnt); 112 | int diff = alg-hw; 113 | int adiff = abs(diff); 114 | sumErr += adiff; 115 | float angO = (double)*(angle_orig+cnt); 116 | float angHw = (*(angle+cnt)).to_double(); 117 | float angAdiff = abs(angO-angHw); 118 | sumAngErr += angAdiff; 119 | cnt++; 120 | rarray[cnt] = hw; // repurposing 'red' array to the bit-accurate monochrome edge-detect output 121 | garray[cnt] = alg; // repurposing 'green' array to the original algorithmic edge-detect output 122 | } 123 | } 124 | 125 | printf("Magnitude: Manhattan norm per pixel %f\n",sumErr/(iH*iW)); 126 | printf("Angle: Manhattan norm per pixel %f\n",sumAngErr/(iH*iW)); 127 | 128 | cout << "Writing algorithmic bitmap output to: " << bmpAlg << endl; 129 | bmp_24_write((char*)bmpAlg.c_str(), iW, iH, garray, garray, garray); 130 | 131 | #ifdef DEBUG 132 | cmd = "display "; 133 | cmd.append(bmpAlg.c_str()); 134 | std::cout << "Display output image file using command: " << cmd << endl; 135 | std::system(cmd.c_str()); 136 | #endif 137 | 138 | cout << "Writing bit-accurate bitmap output to: " << bmpBA << endl; 139 | bmp_24_write((char*)bmpBA.c_str(), iW, iH, rarray, rarray, rarray); 140 | 141 | #ifdef DEBUG 142 | cmd = "display "; 143 | cmd.append(bmpBA.c_str()); 144 | std::cout << "Display output image file using command: " << cmd << endl; 145 | std::system(cmd.c_str()); 146 | #endif 147 | 148 | delete (dat_in_orig); 149 | delete (magn_orig); 150 | delete (angle_orig); 151 | delete (dat_in); 152 | delete (magn); 153 | delete (angle); 154 | delete (rarray); 155 | delete (garray); 156 | delete (barray); 157 | 158 | cout << "Finished" << endl; 159 | 160 | CCS_RETURN(0); 161 | } 162 | -------------------------------------------------------------------------------- /WalkThroughs/EdgeDetect/src/EdgeDetect_CircularBuf.h: -------------------------------------------------------------------------------- 1 | /************************************************************************** 2 | * * 3 | * Edge Detect Design Walkthrough for HLS * 4 | * * 5 | * Software Version: 1.0 * 6 | * * 7 | * Release Date : Tue Jan 14 15:40:43 PST 2020 * 8 | * Release Type : Production Release * 9 | * Release Build : 1.0.0 * 10 | * * 11 | * Copyright 2020, Mentor Graphics Corporation, * 12 | * * 13 | * All Rights Reserved. * 14 | * 15 | ************************************************************************** 16 | * Licensed under the Apache License, Version 2.0 (the "License"); * 17 | * you may not use this file except in compliance with the License. * 18 | * You may obtain a copy of the License at * 19 | * * 20 | * http://www.apache.org/licenses/LICENSE-2.0 * 21 | * * 22 | * Unless required by applicable law or agreed to in writing, software * 23 | * distributed under the License is distributed on an "AS IS" BASIS, * 24 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or * 25 | * implied. * 26 | * See the License for the specific language governing permissions and * 27 | * limitations under the License. * 28 | ************************************************************************** 29 | * * 30 | * The most recent version of this package is available at github. * 31 | * * 32 | *************************************************************************/ 33 | #ifndef _INCLUDED_EDGEDETECT_SINGLEPORT_H_ 34 | #define _INCLUDED_EDGEDETECT_SINGLEPORT_H_ 35 | 36 | // Revision History 37 | // Rev 1 - Coding of edge detection algorithm in C++ 38 | // Rev 2 - Converted to using bit-accurate data types 39 | // Calculated bit growth for internal variables 40 | // Quantized angle values for 5 fractional bits -pi to pi 41 | // Rev 3 - Switch to using HLSLIBS ac_math library for high performance 42 | // math functions. 43 | // Add support for verification using SCVerify 44 | // Rev 4 - Refinining memory architecture for 1PPC 45 | // Rev 5 - Modularized into hierarchy for performance 46 | // Rev 6 - Recode to use single-port memories 47 | // Rev 7 - Recode to make the design programmable for image size 48 | // Rev 8 - Recode to use single-port memories in circular fashion 49 | 50 | #include 51 | //This is Catapult's math library implementation, see docs for details 52 | #include 53 | #include 54 | 55 | // Class for fifo-style hierarchical interconnect objects 56 | #include 57 | 58 | // Include constant kernel definition 59 | #include "edge_defs.h" 60 | #include 61 | 62 | template 63 | class EdgeDetect_CircularBuf 64 | { 65 | // Define some bit-accurate types to use in this model 66 | typedef uint8 pixelType; // input pixel is 0-255 67 | typedef uint16 pixelType2x; // two pixels packed 68 | typedef int9 gradType; // Derivative is max range -255 to 255 69 | typedef uint18 sqType; // Result of 9-bit x 9-bit 70 | typedef ac_fixed<19,19,false> sumType; // Result of 18-bit + 18-bit fixed pt integer for squareroot 71 | typedef uint9 magType; // 9-bit unsigned magnitute result 72 | typedef ac_fixed<8,3,true> angType; // 3 integer bit, 5 fractional bits for quantized angle -pi to pi 73 | 74 | // Static interconnect channels (FIFOs) between blocks 75 | ac_channel dy; 76 | ac_channel dx; 77 | ac_channel dat; // channel for passing input pixels to horizontalDerivative 78 | bool pp; // flag for rotating the buffers 79 | 80 | public: 81 | //Compute number of bits for max image size count, used internally and in testbench 82 | typedef ac_int::val,false> maxW; 83 | typedef ac_int::val,false> maxH; 84 | EdgeDetect_CircularBuf():pp(false) {} 85 | 86 | //-------------------------------------------------------------------------- 87 | // Function: run 88 | // Top interface for data in/out of class. Combines vertical and 89 | // horizontal derivative and magnitude/angle computation. 90 | #pragma hls_design interface 91 | void CCS_BLOCK(run)(ac_channel &dat_in, 92 | maxW &widthIn, 93 | maxH &heightIn, 94 | ac_channel &magn, 95 | ac_channel &angle) 96 | { 97 | verticalDerivative(dat_in, widthIn, heightIn, dat, dy); 98 | horizontalDerivative(dat, widthIn, heightIn, dx); 99 | magnitudeAngle(dx, dy, widthIn, heightIn, magn, angle); 100 | } 101 | 102 | private: 103 | //-------------------------------------------------------------------------- 104 | // Function: verticalDerivative 105 | // Compute the vertical derivative on the input data 106 | #pragma hls_design 107 | void verticalDerivative(ac_channel &dat_in, 108 | maxW &widthIn, 109 | maxH &heightIn, 110 | ac_channel &dat_out, 111 | ac_channel &dy) 112 | { 113 | // Line buffers store pixel line history - Mapped to RAM 114 | pixelType2x line_buf0[imageWidth/2]; 115 | pixelType2x line_buf1[imageWidth/2]; 116 | pixelType2x rdbuf0_pix, rdbuf1_pix; 117 | pixelType2x wrbuf0_pix, wrbuf1_pix; 118 | pixelType pix0, pix1, pix2; 119 | gradType pix; 120 | 121 | // Remove loop upperbounds for RTL code coverage 122 | // Use bit accurate data types on loop iterator 123 | VROW: for (maxH y = 0;; y++) { // One extra iteration to ramp-up window 124 | VCOL: for (maxW x = 0;; x++) { 125 | if ((y < imageHeight) & (x < imageWidth)) { 126 | pix0 = dat_in.read(); // Read streaming interface 127 | } 128 | // Write data cache, write lower 8 on even iterations of COL loop, upper 8 on odd 129 | if ( (x&1) == 0 ) { 130 | wrbuf0_pix.set_slc(0,pix0); 131 | } else { 132 | wrbuf0_pix.set_slc(8,pix0); 133 | } 134 | // Read line buffers into read buffer caches on even iterations of COL loop 135 | if ( (x&1) == 0 ) { 136 | // pp controls which buffer is read as upper, which as lower 137 | rdbuf1_pix = pp ? line_buf1[x/2] : line_buf0[x/2]; 138 | rdbuf0_pix = pp ? line_buf0[x/2] : line_buf1[x/2]; 139 | } else { // Write line buffer caches on odd iterations of COL loop 140 | // Only one buffer is ever written based on pp 141 | if (pp) 142 | line_buf1[x/2] = wrbuf0_pix; // store current line 143 | else 144 | line_buf0[x/2] = wrbuf0_pix; // store current line 145 | } 146 | // Get 8-bit data from read buffer caches, lower 8 on even iterations of COL loop 147 | pix2 = ((x&1)==0) ? rdbuf1_pix.slc<8>(0) : rdbuf1_pix.slc<8>(8); 148 | pix1 = ((x&1)==0) ? rdbuf0_pix.slc<8>(0) : rdbuf0_pix.slc<8>(8); 149 | 150 | // Boundary condition processing 151 | if (y == 1) { 152 | pix2 = pix1; // top boundary (replicate pix1 up to pix2) 153 | } 154 | if (y == imageHeight) { 155 | pix0 = pix1; // bottom boundary (replicate pix1 down to pix0) 156 | } 157 | 158 | // Calculate derivative 159 | pix = pix2*kernel[0] + pix1*kernel[1] + pix0*kernel[2]; 160 | 161 | if (y != 0) { // Write streaming interfaces 162 | dat_out.write(pix1); // Pass thru original data 163 | dy.write(pix); // derivative output 164 | } 165 | // Rotate the buffers at the end of every line 166 | if (x == imageWidth-1) 167 | pp = !pp; 168 | // programmable width exit condition 169 | if (x == maxW(widthIn-1)) // cast to maxW for RTL code coverage 170 | break; 171 | } 172 | // programmable height exit condition 173 | if (y == heightIn) 174 | break; 175 | } 176 | } 177 | 178 | //-------------------------------------------------------------------------- 179 | // Function: horizontalDerivative 180 | // Compute the horizontal derivative on the input data 181 | #pragma hls_design 182 | void horizontalDerivative(ac_channel &dat_in, 183 | maxW &widthIn, 184 | maxH &heightIn, 185 | ac_channel &dx) 186 | { 187 | // pixel buffers store pixel history 188 | pixelType pix_buf0; 189 | pixelType pix_buf1; 190 | 191 | pixelType pix0 = 0; 192 | pixelType pix1 = 0; 193 | pixelType pix2 = 0; 194 | 195 | gradType pix; 196 | 197 | HROW: for (maxH y = 0; ; y++) { 198 | HCOL: for (maxW x = 0; ; x++) { // One extra iteration to ramp-up window 199 | pix2 = pix_buf1; 200 | pix1 = pix_buf0; 201 | if (x <= imageWidth-1) { 202 | pix0 = dat_in.read(); // Read streaming interface 203 | } 204 | if (x == 1) { 205 | pix2 = pix1; // left boundary condition (replicate pix1 left to pix2) 206 | } 207 | if (x == imageWidth) { 208 | pix0 = pix1; // right boundary condition (replicate pix1 right to pix0) 209 | } 210 | 211 | pix_buf1 = pix_buf0; 212 | pix_buf0 = pix0; 213 | // Calculate derivative 214 | pix = pix2*kernel[0] + pix1*kernel[1] + pix0*kernel[2]; 215 | 216 | if (x != 0) { // Write streaming interface 217 | dx.write(pix); // derivative out 218 | } 219 | //programmable width exit condition 220 | if (x == widthIn) // cast to maxW for RTL code coverage 221 | break; 222 | } 223 | // programmable height exit condition 224 | if (y == (maxH)(heightIn-1)) // cast to maxH for RTL code coverage 225 | break; 226 | } 227 | } 228 | 229 | //-------------------------------------------------------------------------- 230 | // Function: magnitudeAngle 231 | // Compute the magnitute and angle based on the horizontal and vertical 232 | // derivative results 233 | #pragma hls_design 234 | void magnitudeAngle(ac_channel &dx_in, 235 | ac_channel &dy_in, 236 | maxW &widthIn, 237 | maxH &heightIn, 238 | ac_channel &magn, 239 | ac_channel &angle) 240 | { 241 | gradType dx, dy; 242 | sqType dx_sq; 243 | sqType dy_sq; 244 | sumType sum; // fixed point integer for sqrt 245 | angType at; 246 | ac_fixed<16,9,false> sq_rt; // square-root return type 247 | 248 | MROW: for (maxH y = 0; ; y++) { 249 | MCOL: for (maxW x = 0; ; x++) { 250 | dx = dx_in.read(); 251 | dy = dy_in.read(); 252 | dx_sq = dx * dx; 253 | dy_sq = dy * dy; 254 | sum = dx_sq + dy_sq; 255 | // Catapult's math library piecewise linear implementation of sqrt and atan2 256 | ac_math::ac_sqrt_pwl(sum,sq_rt); 257 | magn.write(sq_rt.to_uint()); 258 | ac_math::ac_atan2_cordic((ac_fixed<9,9>)dy, (ac_fixed<9,9>) dx, at); 259 | angle.write(at); 260 | // programmable width exit condition 261 | if (x == maxW(widthIn-1)) // cast to maxW for RTL code coverage 262 | break; 263 | } 264 | //programmable height exit condition 265 | if (y == maxH(heightIn-1)) // cast to maxH for RTL code coverage 266 | break; 267 | } 268 | } 269 | 270 | }; 271 | 272 | #endif 273 | 274 | -------------------------------------------------------------------------------- /WalkThroughs/EdgeDetect/src/EdgeDetect_CircularBuf.tcl: -------------------------------------------------------------------------------- 1 | #------------------------------------------------------------ 2 | # Sliding Window Walkthrough - Circular buffers 3 | #------------------------------------------------------------ 4 | 5 | # Establish the location of this script and use it to reference all 6 | # other files in this example 7 | set sfd [file dirname [info script]] 8 | 9 | # Reset the options to the factory defaults 10 | options defaults 11 | options set /Input/CppStandard c++11 12 | 13 | project new 14 | 15 | flow package require /SCVerify 16 | flow package option set /SCVerify/USE_CCS_BLOCK true 17 | flow package option set /SCVerify/INVOKE_ARGS "[file join $sfd image people_gray.bmp] out_algorithm.bmp out_hw.bmp" 18 | 19 | solution file add {$MGC_HOME/shared/include/bmpUtil/bmp_io.cpp} -type C++ -exclude true 20 | solution file add [file join $sfd EdgeDetect_CircularBuf_tb.cpp] -type C++ 21 | options set Output/OutputVHDL false 22 | options set Flows/LowPower/SWITCHING_ACTIVITY_TYPE saif 23 | 24 | solution options set /ComponentLibs/SearchPath $sfd -append 25 | 26 | go analyze 27 | directive set -DESIGN_HIERARCHY {{EdgeDetect_CircularBuf<1296, 864>} {EdgeDetect_CircularBuf<1296, 864>::verticalDerivative} {EdgeDetect_CircularBuf<1296, 864>::horizontalDerivative} {EdgeDetect_CircularBuf<1296, 864>::magnitudeAngle}} 28 | go compile 29 | solution library add nangate-45nm_beh -file {$MGC_HOME/pkgs/siflibs/nangate/nangate-45nm_beh.lib} -- -rtlsyntool OasysRTL 30 | solution library add ram_1k_16_sp 31 | 32 | go libraries 33 | directive set -CLOCKS {clk {-CLOCK_PERIOD 3.33 -CLOCK_EDGE rising -CLOCK_UNCERTAINTY 0.0 -CLOCK_HIGH_TIME 1.665 -RESET_SYNC_NAME rst -RESET_ASYNC_NAME arst_n -RESET_KIND sync -RESET_SYNC_ACTIVE high -RESET_ASYNC_ACTIVE low -ENABLE_ACTIVE high}} 34 | go assembly 35 | directive set /EdgeDetect_CircularBuf<1296,864>/verticalDerivative/core/line_buf0:rsc -MAP_TO_MODULE ram_1k_16_sp.ram_1k_16_sp 36 | directive set /EdgeDetect_CircularBuf<1296,864>/verticalDerivative/core/line_buf1:rsc -MAP_TO_MODULE ram_1k_16_sp.ram_1k_16_sp 37 | directive set /EdgeDetect_CircularBuf<1296,864>/verticalDerivative/core/VROW -PIPELINE_INIT_INTERVAL 1 38 | directive set /EdgeDetect_CircularBuf<1296,864>/horizontalDerivative/core/HROW -PIPELINE_INIT_INTERVAL 1 39 | directive set /EdgeDetect_CircularBuf<1296,864>/magnitudeAngle/core/MROW -PIPELINE_INIT_INTERVAL 1 40 | directive set /EdgeDetect_CircularBuf<1296,864>/magnitudeAngle/core/ac_math::ac_atan2_cordic<9,9,AC_TRN,AC_WRAP,9,9,AC_TRN,AC_WRAP,8,3,AC_TRN,AC_WRAP>:for -UNROLL yes 41 | directive set /EdgeDetect_CircularBuf<1296,864>/widthIn:rsc -MAP_TO_MODULE {[DirectInput]} 42 | directive set /EdgeDetect_CircularBuf<1296,864>/heightIn:rsc -MAP_TO_MODULE {[DirectInput]} 43 | go architect 44 | go extract 45 | -------------------------------------------------------------------------------- /WalkThroughs/EdgeDetect/src/EdgeDetect_CircularBuf_power.tcl: -------------------------------------------------------------------------------- 1 | #------------------------------------------------------------ 2 | # Sliding Window Walkthrough - Circular buffers wiht power measurment 3 | #------------------------------------------------------------ 4 | 5 | # Establish the location of this script and use it to reference all 6 | # other files in this example 7 | set sfd [file dirname [info script]] 8 | 9 | # Reset the options to the factory defaults 10 | options defaults 11 | options set /Input/CppStandard c++11 12 | 13 | project new 14 | 15 | flow package require /SCVerify 16 | flow package option set /SCVerify/USE_CCS_BLOCK true 17 | flow package option set /SCVerify/INVOKE_ARGS "[file join $sfd image people_gray.bmp] out_algorithm.bmp out_hw.bmp" 18 | 19 | solution file add {$MGC_HOME/shared/include/bmpUtil/bmp_io.cpp} -type C++ -exclude true 20 | solution file add [file join $sfd EdgeDetect_SinglePort_Programable_tb.cpp] -type C++ 21 | options set Input/CompilerFlags -DPOWER 22 | options set Output/OutputVHDL false 23 | options set Flows/LowPower/SWITCHING_ACTIVITY_TYPE saif 24 | 25 | solution options set /ComponentLibs/SearchPath $sfd -append 26 | 27 | go analyze 28 | directive set -DESIGN_HIERARCHY {{EdgeDetect_SinglePort<1296, 864>} {EdgeDetect_SinglePort<1296, 864>::verticalDerivative} {EdgeDetect_SinglePort<1296, 864>::horizontalDerivative} {EdgeDetect_SinglePort<1296, 864>::magnitudeAngle}} 29 | go compile 30 | solution library add nangate-45nm_beh -file {$MGC_HOME/pkgs/siflibs/nangate/nangate-45nm_beh.lib} -- -rtlsyntool OasysRTL 31 | solution library add ccs_sample_mem -file {$MGC_HOME/pkgs/siflibs/ccs_sample_mem.lib} 32 | solution library add ram_1k_16_sp 33 | go libraries 34 | directive set -CLOCKS {clk {-CLOCK_PERIOD 3.33 -CLOCK_EDGE rising -CLOCK_UNCERTAINTY 0.0 -CLOCK_HIGH_TIME 1.665 -RESET_SYNC_NAME rst -RESET_ASYNC_NAME arst_n -RESET_KIND sync -RESET_SYNC_ACTIVE high -RESET_ASYNC_ACTIVE low -ENABLE_ACTIVE high}} 35 | go assembly 36 | 37 | directive set /EdgeDetect_SinglePort<1296,864>/verticalDerivative/core/line_buf0:rsc -MAP_TO_MODULE ram_1k_16_sp.ram_1k_16_sp 38 | directive set /EdgeDetect_SinglePort<1296,864>/verticalDerivative/core/line_buf1:rsc -MAP_TO_MODULE ram_1k_16_sp.ram_1k_16_sp 39 | directive set /EdgeDetect_SinglePort<1296,864>/verticalDerivative/core/VROW -PIPELINE_INIT_INTERVAL 1 40 | directive set /EdgeDetect_SinglePort<1296,864>/horizontalDerivative/core/HROW -PIPELINE_INIT_INTERVAL 1 41 | directive set /EdgeDetect_SinglePort<1296,864>/magnitudeAngle/core/MROW -PIPELINE_INIT_INTERVAL 1 42 | directive set /EdgeDetect_SinglePort<1296,864>/magnitudeAngle/core/ac_math::ac_atan2_cordic<9,9,AC_TRN,AC_WRAP,9,9,AC_TRN,AC_WRAP,8,3,AC_TRN,AC_WRAP>:for -UNROLL yes 43 | directive set /EdgeDetect_SinglePort<1296,864>/widthIn:rsc -MAP_TO_MODULE {[DirectInput]} 44 | directive set /EdgeDetect_SinglePort<1296,864>/heightIn:rsc -MAP_TO_MODULE {[DirectInput]} 45 | go architect 46 | go extract 47 | go switch 48 | flow run /PowerAnalysis/report_pre_pwropt_Verilog 49 | 50 | go new 51 | 52 | solution file remove [file join $sfd EdgeDetect_SinglePort_Programable_tb.cpp] 53 | solution file add [file join $sfd EdgeDetect_CircularBuf_tb.cpp] -type C++ 54 | 55 | go analyze 56 | directive set -DESIGN_HIERARCHY {{EdgeDetect_CircularBuf<1296, 864>} {EdgeDetect_CircularBuf<1296, 864>::verticalDerivative} {EdgeDetect_CircularBuf<1296, 864>::horizontalDerivative} {EdgeDetect_CircularBuf<1296, 864>::magnitudeAngle}} 57 | go compile 58 | go libraries 59 | directive set -CLOCKS {clk {-CLOCK_PERIOD 3.33 -CLOCK_EDGE rising -CLOCK_UNCERTAINTY 0.0 -CLOCK_HIGH_TIME 1.665 -RESET_SYNC_NAME rst -RESET_ASYNC_NAME arst_n -RESET_KIND sync -RESET_SYNC_ACTIVE high -RESET_ASYNC_ACTIVE low -ENABLE_ACTIVE high}} 60 | go assembly 61 | directive set /EdgeDetect_CircularBuf<1296,864>/verticalDerivative/core/line_buf0:rsc -MAP_TO_MODULE ram_1k_16_sp.ram_1k_16_sp 62 | directive set /EdgeDetect_CircularBuf<1296,864>/verticalDerivative/core/line_buf1:rsc -MAP_TO_MODULE ram_1k_16_sp.ram_1k_16_sp 63 | directive set /EdgeDetect_CircularBuf<1296,864>/verticalDerivative/core/VROW -PIPELINE_INIT_INTERVAL 1 64 | directive set /EdgeDetect_CircularBuf<1296,864>/horizontalDerivative/core/HROW -PIPELINE_INIT_INTERVAL 1 65 | directive set /EdgeDetect_CircularBuf<1296,864>/magnitudeAngle/core/MROW -PIPELINE_INIT_INTERVAL 1 66 | directive set /EdgeDetect_CircularBuf<1296,864>/magnitudeAngle/core/ac_math::ac_atan2_cordic<9,9,AC_TRN,AC_WRAP,9,9,AC_TRN,AC_WRAP,8,3,AC_TRN,AC_WRAP>:for -UNROLL yes 67 | directive set /EdgeDetect_CircularBuf<1296,864>/widthIn:rsc -MAP_TO_MODULE {[DirectInput]} 68 | directive set /EdgeDetect_CircularBuf<1296,864>/heightIn:rsc -MAP_TO_MODULE {[DirectInput]} 69 | go architect 70 | go extract 71 | go switch 72 | flow run /PowerAnalysis/report_pre_pwropt_Verilog 73 | -------------------------------------------------------------------------------- /WalkThroughs/EdgeDetect/src/EdgeDetect_CircularBuf_tb.cpp: -------------------------------------------------------------------------------- 1 | /************************************************************************** 2 | * * 3 | * Edge Detect Design Walkthrough for HLS * 4 | * * 5 | * Software Version: 1.0 * 6 | * * 7 | * Release Date : Tue Jan 14 15:40:43 PST 2020 * 8 | * Release Type : Production Release * 9 | * Release Build : 1.0.0 * 10 | * * 11 | * Copyright 2020, Mentor Graphics Corporation, * 12 | * * 13 | * All Rights Reserved. * 14 | * 15 | ************************************************************************** 16 | * Licensed under the Apache License, Version 2.0 (the "License"); * 17 | * you may not use this file except in compliance with the License. * 18 | * You may obtain a copy of the License at * 19 | * * 20 | * http://www.apache.org/licenses/LICENSE-2.0 * 21 | * * 22 | * Unless required by applicable law or agreed to in writing, software * 23 | * distributed under the License is distributed on an "AS IS" BASIS, * 24 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or * 25 | * implied. * 26 | * See the License for the specific language governing permissions and * 27 | * limitations under the License. * 28 | ************************************************************************** 29 | * * 30 | * The most recent version of this package is available at github. * 31 | * * 32 | *************************************************************************/ 33 | #include 34 | #include 35 | 36 | using namespace std; 37 | 38 | #include "EdgeDetect_Algorithm.h" 39 | #include "EdgeDetect_CircularBuf.h" 40 | 41 | #include "bmpUtil/bmp_io.hpp" 42 | #include 43 | #include 44 | #include 45 | #include 46 | #include 47 | 48 | CCS_MAIN(int argc, char *argv[]) 49 | { 50 | const int iW = 1296; 51 | const int iH = 864; 52 | EdgeDetect_Algorithm inst0; 53 | EdgeDetect_CircularBuf inst1; 54 | 55 | unsigned long int width = iW; 56 | long int height = iH; 57 | 58 | 59 | EdgeDetect_CircularBuf::maxW widthIn = iW; 60 | #ifndef POWER 61 | EdgeDetect_CircularBuf::maxH heightIn = iH; 62 | #else 63 | EdgeDetect_CircularBuf::maxH heightIn = 30;//use less rows for power analysis 64 | #endif 65 | unsigned char *rarray = new unsigned char[iH*iW]; 66 | unsigned char *garray = new unsigned char[iH*iW]; 67 | unsigned char *barray = new unsigned char[iH*iW]; 68 | 69 | cout << "Loading Input File" << endl; 70 | 71 | if (argc < 3) { 72 | cout << "Usage: " << argv[0] << " " << endl; 73 | CCS_RETURN(-1); 74 | } 75 | 76 | std::string bmpIn(argv[1]); // input bitmap file 77 | std::string bmpAlg(argv[2]); // output bitmap (algorithm) 78 | std::string bmpBA(argv[3]); // output bitmap (bit-accurate) 79 | 80 | bmp_read((char*)bmpIn.c_str(), &width, &height, &rarray, &garray, &barray); 81 | assert(width==iW); 82 | assert(height==iH); 83 | 84 | #ifdef DEBUG 85 | std::string cmd; 86 | cmd = "display "; 87 | cmd.append(bmpIn.c_str()); 88 | std::cout << "Display input image file using command: " << cmd << endl; 89 | std::system(cmd.c_str()); 90 | #endif 91 | 92 | ac_channel dat_in; 93 | ac_channel magn; 94 | ac_channel > angle; 95 | 96 | unsigned char *dat_in_orig = new unsigned char[iH*iW];; 97 | double *magn_orig = new double[iH*iW]; 98 | double *angle_orig = new double[iH*iW]; 99 | 100 | unsigned cnt = 0; 101 | for (int y = 0; y < iH; y++) { 102 | for (int x = 0; x < iW; x++) { 103 | dat_in.write(rarray[cnt]); // just using red component (pseudo monochrome) 104 | dat_in_orig[cnt] = rarray[cnt]; 105 | cnt++; 106 | } 107 | } 108 | 109 | cout << "Running" << endl; 110 | 111 | inst0.run(dat_in_orig,magn_orig,angle_orig); 112 | inst1.run(dat_in,widthIn,heightIn,magn,angle); 113 | 114 | cnt = 0; 115 | float sumErr = 0; 116 | float sumAngErr = 0; 117 | for (int y = 0; y < heightIn; y++) { 118 | for (int x = 0; x < iW; x++) { 119 | int hw = magn.read(); 120 | int alg = (int)*(magn_orig+cnt); 121 | int diff = alg-hw; 122 | int adiff = abs(diff); 123 | sumErr += adiff; 124 | float angO = (double)*(angle_orig+cnt); 125 | float angHw = angle.read().to_double(); 126 | float angAdiff = abs(angO-angHw); 127 | sumAngErr += angAdiff; 128 | cnt++; 129 | rarray[cnt] = hw; // repurposing 'red' array to the bit-accurate monochrome edge-detect output 130 | garray[cnt] = alg; // repurposing 'green' array to the original algorithmic edge-detect output 131 | } 132 | } 133 | 134 | printf("Magnitude: Manhattan norm per pixel %f\n",sumErr/(iH*iW)); 135 | printf("Angle: Manhattan norm per pixel %f\n",sumAngErr/(iH*iW)); 136 | 137 | cout << "Writing algorithmic bitmap output to: " << bmpAlg << endl; 138 | bmp_24_write((char*)bmpAlg.c_str(), iW, iH, garray, garray, garray); 139 | 140 | #ifdef DEBUG 141 | cmd = "display "; 142 | cmd.append(bmpAlg.c_str()); 143 | std::cout << "Display output image file using command: " << cmd << endl; 144 | std::system(cmd.c_str()); 145 | #endif 146 | 147 | cout << "Writing bit-accurate bitmap output to: " << bmpBA << endl; 148 | bmp_24_write((char*)bmpBA.c_str(), iW, iH, rarray, rarray, rarray); 149 | 150 | #ifdef DEBUG 151 | cmd = "display "; 152 | cmd.append(bmpBA.c_str()); 153 | std::cout << "Display output image file using command: " << cmd << endl; 154 | std::system(cmd.c_str()); 155 | #endif 156 | 157 | delete (dat_in_orig); 158 | delete (magn_orig); 159 | delete (angle_orig); 160 | delete (rarray); 161 | delete (garray); 162 | delete (barray); 163 | 164 | cout << "Finished" << endl; 165 | 166 | CCS_RETURN(0); 167 | } 168 | -------------------------------------------------------------------------------- /WalkThroughs/EdgeDetect/src/EdgeDetect_Hierarchy.h: -------------------------------------------------------------------------------- 1 | /************************************************************************** 2 | * * 3 | * Edge Detect Design Walkthrough for HLS * 4 | * * 5 | * Software Version: 1.0 * 6 | * * 7 | * Release Date : Tue Jan 14 15:40:43 PST 2020 * 8 | * Release Type : Production Release * 9 | * Release Build : 1.0.0 * 10 | * * 11 | * Copyright 2020, Mentor Graphics Corporation, * 12 | * * 13 | * All Rights Reserved. * 14 | * 15 | ************************************************************************** 16 | * Licensed under the Apache License, Version 2.0 (the "License"); * 17 | * you may not use this file except in compliance with the License. * 18 | * You may obtain a copy of the License at * 19 | * * 20 | * http://www.apache.org/licenses/LICENSE-2.0 * 21 | * * 22 | * Unless required by applicable law or agreed to in writing, software * 23 | * distributed under the License is distributed on an "AS IS" BASIS, * 24 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or * 25 | * implied. * 26 | * See the License for the specific language governing permissions and * 27 | * limitations under the License. * 28 | ************************************************************************** 29 | * * 30 | * The most recent version of this package is available at github. * 31 | * * 32 | *************************************************************************/ 33 | #ifndef _INCLUDED_EDGEDETECT_HIERARCHY_H_ 34 | #define _INCLUDED_EDGEDETECT_HIERARCHY_H_ 35 | 36 | // Revision History 37 | // Rev 1 - Coding of edge detection algorithm in C++ 38 | // Rev 2 - Converted to using bit-accurate data types 39 | // Calculated bit growth for internal variables 40 | // Quantized angle values for 5 fractional bits -pi to pi 41 | // Rev 3 - Switch to using HLSLIBS ac_math library for high performance 42 | // math functions. 43 | // Add support for verification using SCVerify 44 | // Rev 4 - Refinining memory architecture for 1PPC 45 | // Rev 5 - Modularized into hierarchy for performance 46 | 47 | #include 48 | // This is Catapult's math library implementation, see docs for details 49 | #include 50 | #include 51 | 52 | // Class for fifo-style hierarchical interconnect objects 53 | #include 54 | 55 | // Include constant kernel definition 56 | #include "edge_defs.h" 57 | #include 58 | 59 | class EdgeDetect_Hierarchy 60 | { 61 | // Define some bit-accurate types to use in this model 62 | typedef uint8 pixelType; // input pixel is 0-255 63 | typedef int9 gradType; // Derivative is max range -255 to 255 64 | typedef uint18 sqType; // Result of 9-bit x 9-bit 65 | typedef ac_fixed<19,19,false> sumType; // Result of 18-bit + 18-bit fixed pt integer for squareroot 66 | typedef uint9 magType; // 9-bit unsigned magnitute result 67 | typedef ac_fixed<8,3,true> angType; // 3 integer bit, 5 fractional bits for quantized angle -pi to pi 68 | 69 | // Define some "constants" for use in algorithm 70 | enum { 71 | imageWidth = 1296, 72 | imageHeight = 864 73 | }; 74 | 75 | // Static interconnect channels (FIFOs) between blocks 76 | ac_channel dy; 77 | ac_channel dx; 78 | ac_channel dat; // channel for passing input pixels to horizontalDerivative 79 | 80 | public: 81 | EdgeDetect_Hierarchy() {} 82 | 83 | //-------------------------------------------------------------------------- 84 | // Function: run 85 | // Top interface for data in/out of class. Combines vertical and 86 | // horizontal derivative and magnitude/angle computation. 87 | #pragma hls_design interface 88 | void CCS_BLOCK(run)(ac_channel &dat_in, 89 | ac_channel &magn, 90 | ac_channel &angle) 91 | { 92 | verticalDerivative(dat_in, dat, dy); 93 | horizontalDerivative(dat, dx); 94 | magnitudeAngle(dx, dy, magn, angle); 95 | } 96 | 97 | private: 98 | //-------------------------------------------------------------------------- 99 | // Function: verticalDerivative 100 | // Compute the vertical derivative on the input data 101 | #pragma hls_design 102 | void verticalDerivative(ac_channel &dat_in, 103 | ac_channel &dat_out, 104 | ac_channel &dy) 105 | { 106 | // Line buffers store pixel line history - Mapped to RAM 107 | pixelType line_buf0[imageWidth]; 108 | pixelType line_buf1[imageWidth]; 109 | pixelType pix0, pix1, pix2; 110 | gradType pix; 111 | 112 | VROW: for (int y = 0; y < imageHeight+1; y++) { // One extra iteration to ramp-up window 113 | VCOL: for (int x = 0; x < imageWidth; x++) { 114 | // vertical window of pixels 115 | pix2 = line_buf1[x]; 116 | pix1 = line_buf0[x]; 117 | if (y <= imageHeight-1) { 118 | pix0 = dat_in.read(); // Read streaming interface 119 | } 120 | line_buf1[x] = pix1; // copy previous line 121 | line_buf0[x] = pix0; // store current line 122 | // Boundary condition processing 123 | if (y == 1) { 124 | pix2 = pix1; // top boundary (replicate pix1 up to pix2) 125 | } 126 | if (y == imageHeight) { 127 | pix0 = pix1; // bottom boundary (replicate pix1 down to pix0) 128 | } 129 | 130 | // Calculate derivative 131 | pix = pix2*kernel[0] + pix1*kernel[1] + pix0*kernel[2]; 132 | 133 | if (y != 0) { // Write streaming interfaces 134 | dat_out.write(pix1); // Pass thru original data 135 | dy.write(pix); // derivative output 136 | } 137 | } 138 | } 139 | } 140 | 141 | //-------------------------------------------------------------------------- 142 | // Function: horizontalDerivative 143 | // Compute the horizontal derivative on the input data 144 | #pragma hls_design 145 | void horizontalDerivative(ac_channel &dat_in, 146 | ac_channel &dx) 147 | { 148 | // pixel buffers store pixel history 149 | pixelType pix_buf0; 150 | pixelType pix_buf1; 151 | 152 | pixelType pix0 = 0; 153 | pixelType pix1 = 0; 154 | pixelType pix2 = 0; 155 | 156 | gradType pix; 157 | 158 | HROW: for (int y = 0; y < imageHeight; y++) { 159 | HCOL: for (int x = 0; x < imageWidth+1; x++) { // One extra iteration to ramp-up window 160 | pix2 = pix_buf1; 161 | pix1 = pix_buf0; 162 | if (x <= imageWidth-1) { 163 | pix0 = dat_in.read(); // Read streaming interface 164 | } 165 | if (x == 1) { 166 | pix2 = pix1; // left boundary condition (replicate pix1 left to pix2) 167 | } 168 | if (x == imageWidth) { 169 | pix0 = pix1; // right boundary condition (replicate pix1 right to pix0) 170 | } 171 | 172 | pix_buf1 = pix_buf0; 173 | pix_buf0 = pix0; 174 | // Calculate derivative 175 | pix = pix2*kernel[0] + pix1*kernel[1] + pix0*kernel[2]; 176 | 177 | if (x != 0) { // Write streaming interface 178 | dx.write(pix); // derivative out 179 | } 180 | } 181 | } 182 | } 183 | 184 | //-------------------------------------------------------------------------- 185 | // Function: magnitudeAngle 186 | // Compute the magnitute and angle based on the horizontal and vertical 187 | // derivative results 188 | #pragma hls_design 189 | void magnitudeAngle(ac_channel &dx_in, 190 | ac_channel &dy_in, 191 | ac_channel &magn, 192 | ac_channel &angle) 193 | { 194 | gradType dx, dy; 195 | sqType dx_sq; 196 | sqType dy_sq; 197 | sumType sum; // fixed point integer for sqrt 198 | angType at; 199 | ac_fixed<16,9,false> sq_rt; // square-root return type 200 | 201 | MROW: for (int y = 0; y < imageHeight; y++) { 202 | MCOL: for (int x = 0; x < imageWidth; x++) { 203 | dx = dx_in.read(); 204 | dy = dy_in.read(); 205 | dx_sq = dx * dx; 206 | dy_sq = dy * dy; 207 | sum = dx_sq + dy_sq; 208 | // Catapult's math library piecewise linear implementation of sqrt and atan2 209 | ac_math::ac_sqrt_pwl(sum,sq_rt); 210 | magn.write(sq_rt.to_uint()); 211 | ac_math::ac_atan2_cordic((ac_fixed<9,9>)dy, (ac_fixed<9,9>) dx, at); 212 | angle.write(at); 213 | } 214 | } 215 | } 216 | 217 | }; 218 | 219 | #endif 220 | 221 | -------------------------------------------------------------------------------- /WalkThroughs/EdgeDetect/src/EdgeDetect_Hierarchy.tcl: -------------------------------------------------------------------------------- 1 | #------------------------------------------------------------ 2 | # Sliding Window Walkthrough - Hierarchy 3 | #------------------------------------------------------------ 4 | 5 | # Establish the location of this script and use it to reference all 6 | # other files in this example 7 | set sfd [file dirname [info script]] 8 | 9 | # Reset the options to the factory defaults 10 | options defaults 11 | options set /Input/CppStandard c++11 12 | 13 | project new 14 | 15 | flow package require /SCVerify 16 | flow package option set /SCVerify/USE_CCS_BLOCK true 17 | flow package option set /SCVerify/INVOKE_ARGS "[file join $sfd image people_gray.bmp] out_algorithm.bmp out_hw.bmp" 18 | 19 | solution file add [file join $sfd EdgeDetect_Hierarchy_tb.cpp] -type C++ 20 | solution file add {$MGC_HOME/shared/include/bmpUtil/bmp_io.cpp} -type C++ -exclude true 21 | 22 | go analyze 23 | directive set -DESIGN_HIERARCHY {EdgeDetect_Hierarchy} 24 | go compile 25 | 26 | solution library add nangate-45nm_beh -file {$MGC_HOME/pkgs/siflibs/nangate/nangate-45nm_beh.lib} -- -rtlsyntool OasysRTL 27 | solution library add ccs_sample_mem -file {$MGC_HOME/pkgs/siflibs/ccs_sample_mem.lib} 28 | 29 | go libraries 30 | directive set -CLOCKS {clk {-CLOCK_PERIOD 3.33 -CLOCK_EDGE rising -CLOCK_UNCERTAINTY 0.0 -CLOCK_HIGH_TIME 1.665 -RESET_SYNC_NAME rst -RESET_ASYNC_NAME arst_n -RESET_KIND sync -RESET_SYNC_ACTIVE high -RESET_ASYNC_ACTIVE low -ENABLE_ACTIVE high}} 31 | go assembly 32 | 33 | directive set /EdgeDetect_Hierarchy/verticalDerivative/core/VROW -PIPELINE_INIT_INTERVAL 1 34 | directive set /EdgeDetect_Hierarchy/verticalDerivative/core/VCOL -PIPELINE_INIT_INTERVAL 1 35 | directive set /EdgeDetect_Hierarchy/horizontalDerivative/core/HROW -PIPELINE_INIT_INTERVAL 1 36 | directive set /EdgeDetect_Hierarchy/horizontalDerivative/core/HCOL -PIPELINE_INIT_INTERVAL 1 37 | directive set /EdgeDetect_Hierarchy/magnitudeAngle/core/MROW -PIPELINE_INIT_INTERVAL 1 38 | directive set /EdgeDetect_Hierarchy/magnitudeAngle/core/ac_math::ac_atan2_cordic<9,9,AC_TRN,AC_WRAP,9,9,AC_TRN,AC_WRAP,8,3,AC_TRN,AC_WRAP>:for -UNROLL yes 39 | go architect 40 | ignore_memory_precedences -from *write_mem(line_buf* -to *read_mem(line_buf* 41 | go allocate 42 | go extract 43 | 44 | -------------------------------------------------------------------------------- /WalkThroughs/EdgeDetect/src/EdgeDetect_Hierarchy_tb.cpp: -------------------------------------------------------------------------------- 1 | /************************************************************************** 2 | * * 3 | * Edge Detect Design Walkthrough for HLS * 4 | * * 5 | * Software Version: 1.0 * 6 | * * 7 | * Release Date : Tue Jan 14 15:40:43 PST 2020 * 8 | * Release Type : Production Release * 9 | * Release Build : 1.0.0 * 10 | * * 11 | * Copyright 2020, Mentor Graphics Corporation, * 12 | * * 13 | * All Rights Reserved. * 14 | * 15 | ************************************************************************** 16 | * Licensed under the Apache License, Version 2.0 (the "License"); * 17 | * you may not use this file except in compliance with the License. * 18 | * You may obtain a copy of the License at * 19 | * * 20 | * http://www.apache.org/licenses/LICENSE-2.0 * 21 | * * 22 | * Unless required by applicable law or agreed to in writing, software * 23 | * distributed under the License is distributed on an "AS IS" BASIS, * 24 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or * 25 | * implied. * 26 | * See the License for the specific language governing permissions and * 27 | * limitations under the License. * 28 | ************************************************************************** 29 | * * 30 | * The most recent version of this package is available at github. * 31 | * * 32 | *************************************************************************/ 33 | #include 34 | #include 35 | 36 | using namespace std; 37 | 38 | #include "EdgeDetect_Algorithm.h" 39 | #include "EdgeDetect_Hierarchy.h" 40 | 41 | #include "bmpUtil/bmp_io.hpp" 42 | #include 43 | #include 44 | #include 45 | #include 46 | #include 47 | 48 | CCS_MAIN(int argc, char *argv[]) 49 | { 50 | const int iW = 1296; 51 | const int iH = 864; 52 | EdgeDetect_Algorithm inst0; 53 | EdgeDetect_Hierarchy inst1; 54 | 55 | unsigned long int width = iW; 56 | long int height = iH; 57 | unsigned char *rarray = new unsigned char[iH*iW]; 58 | unsigned char *garray = new unsigned char[iH*iW]; 59 | unsigned char *barray = new unsigned char[iH*iW]; 60 | 61 | cout << "Loading Input File" << endl; 62 | 63 | if (argc < 3) { 64 | cout << "Usage: " << argv[0] << " " << endl; 65 | CCS_RETURN(-1); 66 | } 67 | 68 | std::string bmpIn(argv[1]); // input bitmap file 69 | std::string bmpAlg(argv[2]); // output bitmap (algorithm) 70 | std::string bmpBA(argv[3]); // output bitmap (bit-accurate) 71 | 72 | bmp_read((char*)bmpIn.c_str(), &width, &height, &rarray, &garray, &barray); 73 | assert(width==iW); 74 | assert(height==iH); 75 | 76 | #ifdef DEBUG 77 | std::string cmd; 78 | cmd = "display "; 79 | cmd.append(bmpIn.c_str()); 80 | std::cout << "Display input image file using command: " << cmd << endl; 81 | std::system(cmd.c_str()); 82 | #endif 83 | 84 | ac_channel dat_in; 85 | ac_channel magn; 86 | ac_channel > angle; 87 | 88 | unsigned char *dat_in_orig = new unsigned char[iH*iW];; 89 | double *magn_orig = new double[iH*iW]; 90 | double *angle_orig = new double[iH*iW]; 91 | 92 | unsigned cnt = 0; 93 | for (int y = 0; y < iH; y++) { 94 | for (int x = 0; x < iW; x++) { 95 | dat_in.write(rarray[cnt]); // just using red component (pseudo monochrome) 96 | dat_in_orig[cnt] = rarray[cnt]; 97 | cnt++; 98 | } 99 | } 100 | 101 | cout << "Running" << endl; 102 | 103 | inst0.run(dat_in_orig,magn_orig,angle_orig); 104 | inst1.run(dat_in,magn,angle); 105 | 106 | cnt = 0; 107 | float sumErr = 0; 108 | float sumAngErr = 0; 109 | for (int y = 0; y < iH; y++) { 110 | for (int x = 0; x < iW; x++) { 111 | int hw = magn.read(); 112 | int alg = (int)*(magn_orig+cnt); 113 | int diff = alg-hw; 114 | int adiff = abs(diff); 115 | sumErr += adiff; 116 | float angO = (double)*(angle_orig+cnt); 117 | float angHw = angle.read().to_double(); 118 | float angAdiff = abs(angO-angHw); 119 | sumAngErr += angAdiff; 120 | cnt++; 121 | rarray[cnt] = hw; // repurposing 'red' array to the bit-accurate monochrome edge-detect output 122 | garray[cnt] = alg; // repurposing 'green' array to the original algorithmic edge-detect output 123 | } 124 | } 125 | 126 | printf("Magnitude: Manhattan norm per pixel %f\n",sumErr/(iH*iW)); 127 | printf("Angle: Manhattan norm per pixel %f\n",sumAngErr/(iH*iW)); 128 | 129 | cout << "Writing algorithmic bitmap output to: " << bmpAlg << endl; 130 | bmp_24_write((char*)bmpAlg.c_str(), iW, iH, garray, garray, garray); 131 | 132 | #ifdef DEBUG 133 | cmd = "display "; 134 | cmd.append(bmpAlg.c_str()); 135 | std::cout << "Display output image file using command: " << cmd << endl; 136 | std::system(cmd.c_str()); 137 | #endif 138 | 139 | cout << "Writing bit-accurate bitmap output to: " << bmpBA << endl; 140 | bmp_24_write((char*)bmpBA.c_str(), iW, iH, rarray, rarray, rarray); 141 | 142 | #ifdef DEBUG 143 | cmd = "display "; 144 | cmd.append(bmpBA.c_str()); 145 | std::cout << "Display output image file using command: " << cmd << endl; 146 | std::system(cmd.c_str()); 147 | #endif 148 | 149 | delete (dat_in_orig); 150 | delete (magn_orig); 151 | delete (angle_orig); 152 | delete (rarray); 153 | delete (garray); 154 | delete (barray); 155 | 156 | cout << "Finished" << endl; 157 | 158 | CCS_RETURN(0); 159 | } 160 | -------------------------------------------------------------------------------- /WalkThroughs/EdgeDetect/src/EdgeDetect_MemoryArch.h: -------------------------------------------------------------------------------- 1 | /************************************************************************** 2 | * * 3 | * Edge Detect Design Walkthrough for HLS * 4 | * * 5 | * Software Version: 1.0 * 6 | * * 7 | * Release Date : Tue Jan 14 15:40:43 PST 2020 * 8 | * Release Type : Production Release * 9 | * Release Build : 1.0.0 * 10 | * * 11 | * Copyright 2020, Mentor Graphics Corporation, * 12 | * * 13 | * All Rights Reserved. * 14 | * 15 | ************************************************************************** 16 | * Licensed under the Apache License, Version 2.0 (the "License"); * 17 | * you may not use this file except in compliance with the License. * 18 | * You may obtain a copy of the License at * 19 | * * 20 | * http://www.apache.org/licenses/LICENSE-2.0 * 21 | * * 22 | * Unless required by applicable law or agreed to in writing, software * 23 | * distributed under the License is distributed on an "AS IS" BASIS, * 24 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or * 25 | * implied. * 26 | * See the License for the specific language governing permissions and * 27 | * limitations under the License. * 28 | ************************************************************************** 29 | * * 30 | * The most recent version of this package is available at github. * 31 | * * 32 | *************************************************************************/ 33 | #ifndef _INCLUDED_EDGEDETECT_MEMORYARCH_H_ 34 | #define _INCLUDED_EDGEDETECT_MEMORYARCH_H_ 35 | 36 | // Revision History 37 | // Rev 1 - Coding of edge detection algorithm in C++ 38 | // Rev 2 - Converted to using bit-accurate data types 39 | // Calculated bit growth for internal variables 40 | // Quantized angle values for 5 fractional bits -pi to pi 41 | // Rev 3 - Switch to using HLSLIBS ac_math library for high performance 42 | // math functions. 43 | // Add support for verification using SCVerify 44 | // Rev 4 - Refinining memory architecture for 1PPC 45 | 46 | #include 47 | // This is Catapult's math library implementation, see docs for details 48 | #include 49 | #include 50 | 51 | // Include constant kernel definition 52 | #include "edge_defs.h" 53 | #include 54 | 55 | class EdgeDetect_MemoryArch 56 | { 57 | // Define some bit-accurate types to use in this model 58 | typedef uint8 pixelType; // input pixel is 0-255 59 | typedef int9 gradType; // Derivative is max range -255 to 255 60 | typedef uint18 sqType; // Result of 9-bit x 9-bit 61 | typedef ac_fixed<19,19,false> sumType; // Result of 18-bit + 18-bit fixed pt integer for squareroot 62 | typedef uint9 magType; // 9-bit unsigned magnitute result 63 | typedef ac_fixed<8,3,true> angType; // 3 integer bit, 5 fractional bits for quantized angle -pi to pi 64 | 65 | // Define some "constants" for use in algorithm 66 | enum { 67 | imageWidth = 1296, 68 | imageHeight = 864 69 | }; 70 | 71 | public: 72 | EdgeDetect_MemoryArch() {} 73 | 74 | //-------------------------------------------------------------------------- 75 | // Function: run 76 | // Top interface for data in/out of class. Combines vertical and 77 | // horizontal derivative and magnitude/angle computation. 78 | #pragma hls_design interface 79 | void CCS_BLOCK(run)(pixelType dat_in[imageHeight][imageWidth], 80 | magType magn[imageHeight][imageWidth], 81 | angType angle[imageHeight][imageWidth]) 82 | { 83 | // allocate buffers for image data 84 | gradType dx[imageHeight][imageWidth]; 85 | gradType dy[imageHeight][imageWidth]; 86 | 87 | verticalDerivative(dat_in, dy); 88 | horizontalDerivative(dat_in,dx); 89 | magnitudeAngle(dx, dy, magn, angle); 90 | } 91 | 92 | //-------------------------------------------------------------------------- 93 | // Function: verticalDerivative 94 | // Compute the vertical derivative on the input data 95 | void verticalDerivative(pixelType dat_in[imageHeight][imageWidth], 96 | gradType dy[imageHeight][imageWidth]) 97 | { 98 | // Line buffers store pixel line history - Mapped to RAM 99 | pixelType line_buf0[imageWidth]; 100 | pixelType line_buf1[imageWidth]; 101 | pixelType pix0,pix1, pix2; 102 | 103 | VROW: for (int y = 0; y < imageHeight+1; y++) { // One extra iteration to ramp-up window 104 | VCOL: for (int x = 0; x < imageWidth; x++) { 105 | // vertical window of pixels 106 | pix2 = line_buf1[x]; 107 | pix1 = line_buf0[x]; 108 | if (y <= imageHeight-1) { 109 | pix0 = dat_in[y][x]; // Read memory while in bounds 110 | } 111 | line_buf1[x] = pix1; // copy previous line 112 | line_buf0[x] = pix0; // store current line 113 | // Boundary condition processing 114 | if (y == 1) { 115 | pix2 = pix1; // top boundary (replicate pix1 up to pix2) 116 | } 117 | if (y == imageHeight) { 118 | pix0 = pix1; // bottom boundary (replicate pix1 down to pix0) 119 | } 120 | 121 | // Calculate derivative 122 | if (y > 0) { 123 | // wait till window ramp-up and adjust index i 124 | dy[y-1][x] = pix2*kernel[0] + pix1*kernel[1] + pix0*kernel[2]; 125 | } 126 | } 127 | } 128 | } 129 | 130 | //-------------------------------------------------------------------------- 131 | // Function: horizontalDerivative 132 | // Compute the horizontal derivative on the input data 133 | void horizontalDerivative(pixelType dat_in[imageHeight][imageWidth], 134 | gradType dx[imageHeight][imageWidth]) 135 | { 136 | // pixel buffers store pixel history 137 | pixelType pix_buf0; 138 | pixelType pix_buf1; 139 | 140 | pixelType pix0 = 0; 141 | pixelType pix1 = 0; 142 | pixelType pix2 = 0; 143 | 144 | HROW: for (int y = 0; y < imageHeight; y++) { 145 | HCOL: for (int x = 0; x < imageWidth+1; x++) { 146 | pix2 = pix_buf1; 147 | pix1 = pix_buf0; 148 | if (x <= imageWidth-1) { 149 | pix0 = dat_in[y][x]; // Read memory while in bounds 150 | } 151 | if (x == 1) { 152 | pix2 = pix1; // left boundary condition (replicate pix1 left to pix2) 153 | } 154 | if (x == imageWidth) { 155 | pix0 = pix1; // right boundary condition (replicate pix1 right to pix0) 156 | } 157 | 158 | pix_buf1 = pix_buf0; 159 | pix_buf0 = pix0; 160 | // Calculate derivative 161 | if (x > 0) { 162 | // wait till window ramp-up and adjust index j 163 | dx[y][x-1] = pix2*kernel[0] + pix1*kernel[1] + pix0*kernel[2]; 164 | } 165 | } 166 | } 167 | } 168 | 169 | //-------------------------------------------------------------------------- 170 | // Function: magnitudeAngle 171 | // Compute the magnitute and angle based on the horizontal and vertical 172 | // derivative results 173 | void magnitudeAngle(gradType dx[imageHeight][imageWidth], 174 | gradType dy[imageHeight][imageWidth], 175 | magType magn[imageHeight][imageWidth], 176 | angType angle[imageHeight][imageWidth]) 177 | { 178 | sqType dx_sq; 179 | sqType dy_sq; 180 | sumType sum; // fixed point integer for sqrt 181 | angType at; 182 | ac_fixed<16,9,false> sq_rt; // square-root return type 183 | 184 | MROW: for (int y = 0; y < imageHeight; y++) { 185 | MCOL: for (int x = 0; x < imageWidth; x++) { 186 | dx_sq = dx[y][x] * dx[y][x]; 187 | dy_sq = dy[y][x] * dy[y][x]; 188 | sum = dx_sq + dy_sq; 189 | // Catapult's math library piecewise linear implementation of sqrt and atan2 190 | ac_math::ac_sqrt_pwl(sum,sq_rt); 191 | magn[y][x] = sq_rt.to_uint(); 192 | ac_math::ac_atan2_cordic((ac_fixed<9,9>) (dy[y][x]), (ac_fixed<9,9>) (dx[y][x]), at); 193 | angle[y][x] = at; 194 | } 195 | } 196 | } 197 | 198 | }; 199 | 200 | #endif 201 | 202 | -------------------------------------------------------------------------------- /WalkThroughs/EdgeDetect/src/EdgeDetect_MemoryArch.tcl: -------------------------------------------------------------------------------- 1 | #------------------------------------------------------------ 2 | # Sliding Window Walkthrough - MemoryArch 3 | #------------------------------------------------------------ 4 | 5 | # Establish the location of this script and use it to reference all 6 | # other files in this example 7 | set sfd [file dirname [info script]] 8 | 9 | # Reset the options to the factory defaults 10 | options defaults 11 | options set /Input/CppStandard c++11 12 | 13 | project new 14 | 15 | flow package require /SCVerify 16 | flow package option set /SCVerify/USE_CCS_BLOCK true 17 | flow package option set /SCVerify/INVOKE_ARGS "[file join $sfd image people_gray.bmp] out_algorithm.bmp out_hw.bmp" 18 | 19 | solution file add [file join $sfd EdgeDetect_MemoryArch_tb.cpp] -type C++ 20 | solution file add {$MGC_HOME/shared/include/bmpUtil/bmp_io.cpp} -type C++ -exclude true 21 | 22 | go analyze 23 | directive set -DESIGN_HIERARCHY EdgeDetect_MemoryArch 24 | go compile 25 | 26 | solution library add nangate-45nm_beh -file {$MGC_HOME/pkgs/siflibs/nangate/nangate-45nm_beh.lib} -- -rtlsyntool OasysRTL 27 | solution library add ccs_sample_mem -file {$MGC_HOME/pkgs/siflibs/ccs_sample_mem.lib} 28 | 29 | go libraries 30 | directive set -CLOCKS {clk {-CLOCK_PERIOD 3.33 -CLOCK_EDGE rising -CLOCK_UNCERTAINTY 0.0 -CLOCK_HIGH_TIME 1.665 -RESET_SYNC_NAME rst -RESET_ASYNC_NAME arst_n -RESET_KIND sync -RESET_SYNC_ACTIVE high -RESET_ASYNC_ACTIVE low -ENABLE_ACTIVE high}} 31 | go assembly 32 | directive set /EdgeDetect_MemoryArch/run/VROW -MERGEABLE false 33 | directive set /EdgeDetect_MemoryArch/run/VCOL -MERGEABLE false 34 | directive set /EdgeDetect_MemoryArch/run/HROW -MERGEABLE false 35 | directive set /EdgeDetect_MemoryArch/run/HCOL -MERGEABLE false 36 | directive set /EdgeDetect_MemoryArch/run/MROW -MERGEABLE false 37 | directive set /EdgeDetect_MemoryArch/run/MCOL -MERGEABLE false 38 | directive set /EdgeDetect_MemoryArch/run/VCOL -PIPELINE_INIT_INTERVAL 1 39 | directive set /EdgeDetect_MemoryArch/run/HCOL -PIPELINE_INIT_INTERVAL 1 40 | directive set /EdgeDetect_MemoryArch/run/MCOL -PIPELINE_INIT_INTERVAL 1 41 | directive set /EdgeDetect_MemoryArch/run/ac_math::ac_atan2_cordic<9,9,AC_TRN,AC_WRAP,9,9,AC_TRN,AC_WRAP,8,3,AC_TRN,AC_WRAP>:for -UNROLL yes 42 | go extract 43 | 44 | -------------------------------------------------------------------------------- /WalkThroughs/EdgeDetect/src/EdgeDetect_MemoryArch_tb.cpp: -------------------------------------------------------------------------------- 1 | /************************************************************************** 2 | * * 3 | * Edge Detect Design Walkthrough for HLS * 4 | * * 5 | * Software Version: 1.0 * 6 | * * 7 | * Release Date : Tue Jan 14 15:40:43 PST 2020 * 8 | * Release Type : Production Release * 9 | * Release Build : 1.0.0 * 10 | * * 11 | * Copyright 2020, Mentor Graphics Corporation, * 12 | * * 13 | * All Rights Reserved. * 14 | * 15 | ************************************************************************** 16 | * Licensed under the Apache License, Version 2.0 (the "License"); * 17 | * you may not use this file except in compliance with the License. * 18 | * You may obtain a copy of the License at * 19 | * * 20 | * http://www.apache.org/licenses/LICENSE-2.0 * 21 | * * 22 | * Unless required by applicable law or agreed to in writing, software * 23 | * distributed under the License is distributed on an "AS IS" BASIS, * 24 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or * 25 | * implied. * 26 | * See the License for the specific language governing permissions and * 27 | * limitations under the License. * 28 | ************************************************************************** 29 | * * 30 | * The most recent version of this package is available at github. * 31 | * * 32 | *************************************************************************/ 33 | #include 34 | #include 35 | 36 | using namespace std; 37 | 38 | #include "EdgeDetect_Algorithm.h" 39 | #include "EdgeDetect_MemoryArch.h" 40 | 41 | #include "bmpUtil/bmp_io.hpp" 42 | #include 43 | #include 44 | #include 45 | #include 46 | #include 47 | 48 | CCS_MAIN(int argc, char *argv[]) 49 | { 50 | const int iW = 1296; 51 | const int iH = 864; 52 | EdgeDetect_Algorithm inst0; 53 | EdgeDetect_MemoryArch inst1; 54 | 55 | unsigned long int width = iW; 56 | long int height = iH; 57 | unsigned char *rarray = new unsigned char[iH*iW]; 58 | unsigned char *garray = new unsigned char[iH*iW]; 59 | unsigned char *barray = new unsigned char[iH*iW]; 60 | 61 | cout << "Loading Input File" << endl; 62 | 63 | if (argc < 3) { 64 | cout << "Usage: " << argv[0] << " " << endl; 65 | CCS_RETURN(-1); 66 | } 67 | 68 | std::string bmpIn(argv[1]); // input bitmap file 69 | std::string bmpAlg(argv[2]); // output bitmap (algorithm) 70 | std::string bmpBA(argv[3]); // output bitmap (bit-accurate) 71 | 72 | bmp_read((char*)bmpIn.c_str(), &width, &height, &rarray, &garray, &barray); 73 | assert(width==iW); 74 | assert(height==iH); 75 | 76 | #ifdef DEBUG 77 | std::string cmd; 78 | cmd = "display "; 79 | cmd.append(bmpIn.c_str()); 80 | std::cout << "Display input image file using command: " << cmd << endl; 81 | std::system(cmd.c_str()); 82 | #endif 83 | 84 | typedef uint8 (array_uint8)[iW]; 85 | array_uint8 *dat_in = new uint8[iH][iW]; 86 | 87 | typedef uint9 (array_uint9)[iW]; 88 | array_uint9 *magn = new uint9[iH][iW]; 89 | 90 | typedef ac_fixed<8,3> (array_af83)[iW]; 91 | array_af83 *angle = new ac_fixed<8,3>[iH][iW]; 92 | 93 | unsigned char *dat_in_orig = new unsigned char[iH*iW];; 94 | double *magn_orig = new double[iH*iW]; 95 | double *angle_orig = new double[iH*iW]; 96 | 97 | unsigned cnt = 0; 98 | for (int y = 0; y < iH; y++) { 99 | for (int x = 0; x < iW; x++) { 100 | dat_in[y][x] = rarray[cnt]; // just using red component (pseudo monochrome) 101 | dat_in_orig[cnt] = rarray[cnt]; 102 | cnt++; 103 | } 104 | } 105 | 106 | cout << "Running" << endl; 107 | 108 | inst0.run(dat_in_orig,magn_orig,angle_orig); 109 | inst1.run(dat_in,magn,angle); 110 | 111 | cnt = 0; 112 | float sumErr = 0; 113 | float sumAngErr = 0; 114 | for (int y = 0; y < iH; y++) { 115 | for (int x = 0; x < iW; x++) { 116 | int hw = magn[y][x]; // *(magn+cnt); 117 | int alg = (int)*(magn_orig+cnt); 118 | int diff = alg-hw; 119 | int adiff = abs(diff); 120 | sumErr += adiff; 121 | float angO = (double)*(angle_orig+cnt); 122 | float angHw = angle[y][x].to_double(); // (*(angle+cnt)).to_double(); 123 | float angAdiff = abs(angO-angHw); 124 | sumAngErr += angAdiff; 125 | cnt++; 126 | rarray[cnt] = hw; // repurposing 'red' array to the bit-accurate monochrome edge-detect output 127 | garray[cnt] = alg; // repurposing 'green' array to the original algorithmic edge-detect output 128 | } 129 | } 130 | 131 | printf("Magnitude: Manhattan norm per pixel %f\n",sumErr/(iH*iW)); 132 | printf("Angle: Manhattan norm per pixel %f\n",sumAngErr/(iH*iW)); 133 | 134 | cout << "Writing algorithmic bitmap output to: " << bmpAlg << endl; 135 | bmp_24_write((char*)bmpAlg.c_str(), iW, iH, garray, garray, garray); 136 | 137 | #ifdef DEBUG 138 | cmd = "display "; 139 | cmd.append(bmpAlg.c_str()); 140 | std::cout << "Display output image file using command: " << cmd << endl; 141 | std::system(cmd.c_str()); 142 | #endif 143 | 144 | cout << "Writing bit-accurate bitmap output to: " << bmpBA << endl; 145 | bmp_24_write((char*)bmpBA.c_str(), iW, iH, rarray, rarray, rarray); 146 | 147 | #ifdef DEBUG 148 | cmd = "display "; 149 | cmd.append(bmpBA.c_str()); 150 | std::cout << "Display output image file using command: " << cmd << endl; 151 | std::system(cmd.c_str()); 152 | #endif 153 | 154 | delete (dat_in_orig); 155 | delete (magn_orig); 156 | delete (angle_orig); 157 | delete (dat_in); 158 | delete (magn); 159 | delete (angle); 160 | delete (rarray); 161 | delete (garray); 162 | delete (barray); 163 | 164 | cout << "Finished" << endl; 165 | 166 | CCS_RETURN(0); 167 | } 168 | -------------------------------------------------------------------------------- /WalkThroughs/EdgeDetect/src/EdgeDetect_SinglePort.h: -------------------------------------------------------------------------------- 1 | /************************************************************************** 2 | * * 3 | * Edge Detect Design Walkthrough for HLS * 4 | * * 5 | * Software Version: 1.0 * 6 | * * 7 | * Release Date : Tue Jan 14 15:40:43 PST 2020 * 8 | * Release Type : Production Release * 9 | * Release Build : 1.0.0 * 10 | * * 11 | * Copyright 2020, Mentor Graphics Corporation, * 12 | * * 13 | * All Rights Reserved. * 14 | * 15 | ************************************************************************** 16 | * Licensed under the Apache License, Version 2.0 (the "License"); * 17 | * you may not use this file except in compliance with the License. * 18 | * You may obtain a copy of the License at * 19 | * * 20 | * http://www.apache.org/licenses/LICENSE-2.0 * 21 | * * 22 | * Unless required by applicable law or agreed to in writing, software * 23 | * distributed under the License is distributed on an "AS IS" BASIS, * 24 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or * 25 | * implied. * 26 | * See the License for the specific language governing permissions and * 27 | * limitations under the License. * 28 | ************************************************************************** 29 | * * 30 | * The most recent version of this package is available at github. * 31 | * * 32 | *************************************************************************/ 33 | #ifndef _INCLUDED_EDGEDETECT_SINGLEPORT_H_ 34 | #define _INCLUDED_EDGEDETECT_SINGLEPORT_H_ 35 | 36 | // Revision History 37 | // Rev 1 - Coding of edge detection algorithm in C++ 38 | // Rev 2 - Converted to using bit-accurate data types 39 | // Calculated bit growth for internal variables 40 | // Quantized angle values for 5 fractional bits -pi to pi 41 | // Rev 3 - Switch to using HLSLIBS ac_math library for high performance 42 | // math functions. 43 | // Add support for verification using SCVerify 44 | // Rev 4 - Refinining memory architecture for 1PPC 45 | // Rev 5 - Modularized into hierarchy for performance 46 | // Rev 6 - Recode to use single-port memories 47 | 48 | #include 49 | //This is Catapult's math library implementation, see docs for details 50 | #include 51 | #include 52 | 53 | // Class for fifo-style hierarchical interconnect objects 54 | #include 55 | 56 | // Include constant kernel definition 57 | #include "edge_defs.h" 58 | #include 59 | 60 | class EdgeDetect_SinglePort 61 | { 62 | // Define some bit-accurate types to use in this model 63 | typedef uint8 pixelType; // input pixel is 0-255 64 | typedef uint16 pixelType2x; // two pixels packed 65 | typedef int9 gradType; // Derivative is max range -255 to 255 66 | typedef uint18 sqType; // Result of 9-bit x 9-bit 67 | typedef ac_fixed<19,19,false> sumType; // Result of 18-bit + 18-bit fixed pt integer for squareroot 68 | typedef uint9 magType; // 9-bit unsigned magnitute result 69 | typedef ac_fixed<8,3,true> angType; // 3 integer bit, 5 fractional bits for quantized angle -pi to pi 70 | 71 | // Define some "constants" for use in algorithm 72 | enum { 73 | imageWidth = 1296, 74 | imageHeight = 864 75 | }; 76 | 77 | // Static interconnect channels (FIFOs) between blocks 78 | ac_channel dy; 79 | ac_channel dx; 80 | ac_channel dat; // channel for passing input pixels to horizontalDerivative 81 | 82 | public: 83 | EdgeDetect_SinglePort() {} 84 | 85 | //-------------------------------------------------------------------------- 86 | // Function: run 87 | // Top interface for data in/out of class. Combines vertical and 88 | // horizontal derivative and magnitude/angle computation. 89 | #pragma hls_design interface 90 | void CCS_BLOCK(run)(ac_channel &dat_in, 91 | ac_channel &magn, 92 | ac_channel &angle) 93 | { 94 | verticalDerivative(dat_in, dat, dy); 95 | horizontalDerivative(dat, dx); 96 | magnitudeAngle(dx, dy, magn, angle); 97 | } 98 | 99 | private: 100 | //-------------------------------------------------------------------------- 101 | // Function: verticalDerivative 102 | // Compute the vertical derivative on the input data 103 | #pragma hls_design 104 | void verticalDerivative(ac_channel &dat_in, 105 | ac_channel &dat_out, 106 | ac_channel &dy) 107 | { 108 | // Line buffers store pixel line history - Mapped to RAM 109 | pixelType2x line_buf0[imageWidth/2]; 110 | pixelType2x line_buf1[imageWidth/2]; 111 | pixelType2x rdbuf0_pix, rdbuf1_pix; 112 | pixelType2x wrbuf0_pix, wrbuf1_pix; 113 | pixelType pix0, pix1, pix2; 114 | gradType pix; 115 | 116 | VROW: for (int y = 0; y < imageHeight+1; y++) { // One extra iteration to ramp-up window 117 | VCOL: for (int x = 0; x < imageWidth; x++) { 118 | if (y <= imageHeight-1) { 119 | pix0 = dat_in.read(); // Read streaming interface 120 | } 121 | // Write data cache, write lower 8 on even iterations of COL loop, upper 8 on odd 122 | if ( (x&1) == 0 ) { 123 | wrbuf0_pix.set_slc(0,pix0); 124 | } else { 125 | wrbuf0_pix.set_slc(8,pix0); 126 | } 127 | // Read line buffers into read buffer caches on even iterations of COL loop 128 | if ( (x&1) == 0 ) { 129 | // vertical window of pixels 130 | rdbuf1_pix = line_buf1[x/2]; 131 | rdbuf0_pix = line_buf0[x/2]; 132 | } else { // Write line buffer caches on odd iterations of COL loop 133 | line_buf1[x/2] = rdbuf0_pix; // copy previous line 134 | line_buf0[x/2] = wrbuf0_pix; // store current line 135 | } 136 | // Get 8-bit data from read buffer caches, lower 8 on even iterations of COL loop 137 | pix2 = ((x&1)==0) ? rdbuf1_pix.slc<8>(0) : rdbuf1_pix.slc<8>(8); 138 | pix1 = ((x&1)==0) ? rdbuf0_pix.slc<8>(0) : rdbuf0_pix.slc<8>(8); 139 | 140 | // Boundary condition processing 141 | if (y == 1) { 142 | pix2 = pix1; // top boundary (replicate pix1 up to pix2) 143 | } 144 | if (y == imageHeight) { 145 | pix0 = pix1; // bottom boundary (replicate pix1 down to pix0) 146 | } 147 | 148 | // Calculate derivative 149 | pix = pix2*kernel[0] + pix1*kernel[1] + pix0*kernel[2]; 150 | 151 | if (y != 0) { // Write streaming interfaces 152 | dat_out.write(pix1); // Pass thru original data 153 | dy.write(pix); // derivative output 154 | } 155 | } 156 | } 157 | } 158 | 159 | //-------------------------------------------------------------------------- 160 | // Function: horizontalDerivative 161 | // Compute the horizontal derivative on the input data 162 | #pragma hls_design 163 | void horizontalDerivative(ac_channel &dat_in, 164 | ac_channel &dx) 165 | { 166 | // pixel buffers store pixel history 167 | pixelType pix_buf0; 168 | pixelType pix_buf1; 169 | 170 | pixelType pix0 = 0; 171 | pixelType pix1 = 0; 172 | pixelType pix2 = 0; 173 | 174 | gradType pix; 175 | 176 | HROW: for (int y = 0; y < imageHeight; y++) { 177 | HCOL: for (int x = 0; x < imageWidth+1; x++) { // One extra iteration to ramp-up window 178 | pix2 = pix_buf1; 179 | pix1 = pix_buf0; 180 | if (x <= imageWidth-1) { 181 | pix0 = dat_in.read(); // Read streaming interface 182 | } 183 | if (x == 1) { 184 | pix2 = pix1; // left boundary condition (replicate pix1 left to pix2) 185 | } 186 | if (x == imageWidth) { 187 | pix0 = pix1; // right boundary condition (replicate pix1 right to pix0) 188 | } 189 | 190 | pix_buf1 = pix_buf0; 191 | pix_buf0 = pix0; 192 | // Calculate derivative 193 | pix = pix2*kernel[0] + pix1*kernel[1] + pix0*kernel[2]; 194 | 195 | if (x != 0) { // Write streaming interface 196 | dx.write(pix); // derivative out 197 | } 198 | } 199 | } 200 | } 201 | 202 | //-------------------------------------------------------------------------- 203 | // Function: magnitudeAngle 204 | // Compute the magnitute and angle based on the horizontal and vertical 205 | // derivative results 206 | #pragma hls_design 207 | void magnitudeAngle(ac_channel &dx_in, 208 | ac_channel &dy_in, 209 | ac_channel &magn, 210 | ac_channel &angle) 211 | { 212 | gradType dx, dy; 213 | sqType dx_sq; 214 | sqType dy_sq; 215 | sumType sum; // fixed point integer for sqrt 216 | angType at; 217 | ac_fixed<16,9,false> sq_rt; // square-root return type 218 | 219 | MROW: for (int y = 0; y < imageHeight; y++) { 220 | MCOL: for (int x = 0; x < imageWidth; x++) { 221 | dx = dx_in.read(); 222 | dy = dy_in.read(); 223 | dx_sq = dx * dx; 224 | dy_sq = dy * dy; 225 | sum = dx_sq + dy_sq; 226 | // Catapult's math library piecewise linear implementation of sqrt and atan2 227 | ac_math::ac_sqrt_pwl(sum,sq_rt); 228 | magn.write(sq_rt.to_uint()); 229 | ac_math::ac_atan2_cordic((ac_fixed<9,9>)dy, (ac_fixed<9,9>) dx, at); 230 | angle.write(at); 231 | } 232 | } 233 | } 234 | 235 | }; 236 | 237 | #endif 238 | 239 | -------------------------------------------------------------------------------- /WalkThroughs/EdgeDetect/src/EdgeDetect_SinglePort.tcl: -------------------------------------------------------------------------------- 1 | #------------------------------------------------------------ 2 | # Sliding Window Walkthrough - SinglePort 3 | #------------------------------------------------------------ 4 | 5 | # Establish the location of this script and use it to reference all 6 | # other files in this example 7 | set sfd [file dirname [info script]] 8 | 9 | # Reset the options to the factory defaults 10 | options defaults 11 | options set /Input/CppStandard c++11 12 | 13 | project new 14 | 15 | flow package require /SCVerify 16 | flow package option set /SCVerify/USE_CCS_BLOCK true 17 | flow package option set /SCVerify/INVOKE_ARGS "[file join $sfd image people_gray.bmp] out_algorithm.bmp out_hw.bmp" 18 | 19 | solution file add [file join $sfd EdgeDetect_SinglePort_tb.cpp] -type C++ 20 | solution file add {$MGC_HOME/shared/include/bmpUtil/bmp_io.cpp} -type C++ -exclude true 21 | 22 | go analyze 23 | directive set -DESIGN_HIERARCHY {{EdgeDetect_SinglePort} {EdgeDetect_SinglePort::verticalDerivative} {EdgeDetect_SinglePort::horizontalDerivative} {EdgeDetect_SinglePort::magnitudeAngle}} 24 | go compile 25 | 26 | solution library add nangate-45nm_beh -file {$MGC_HOME/pkgs/siflibs/nangate/nangate-45nm_beh.lib} -- -rtlsyntool OasysRTL 27 | solution library add ccs_sample_mem -file {$MGC_HOME/pkgs/siflibs/ccs_sample_mem.lib} 28 | 29 | go libraries 30 | directive set -CLOCKS {clk {-CLOCK_PERIOD 3.33 -CLOCK_EDGE rising -CLOCK_UNCERTAINTY 0.0 -CLOCK_HIGH_TIME 1.665 -RESET_SYNC_NAME rst -RESET_ASYNC_NAME arst_n -RESET_KIND sync -RESET_SYNC_ACTIVE high -RESET_ASYNC_ACTIVE low -ENABLE_ACTIVE high}} 31 | go assembly 32 | 33 | directive set /EdgeDetect_SinglePort/verticalDerivative/core/VROW -PIPELINE_INIT_INTERVAL 1 34 | directive set /EdgeDetect_SinglePort/verticalDerivative/core/VCOL -PIPELINE_INIT_INTERVAL 1 35 | directive set /EdgeDetect_SinglePort/horizontalDerivative/core/HROW -PIPELINE_INIT_INTERVAL 1 36 | directive set /EdgeDetect_SinglePort/horizontalDerivative/core/HCOL -PIPELINE_INIT_INTERVAL 1 37 | directive set /EdgeDetect_SinglePort/magnitudeAngle/core/MROW -PIPELINE_INIT_INTERVAL 1 38 | directive set /EdgeDetect_SinglePort/magnitudeAngle/core/ac_math::ac_atan2_cordic<9,9,AC_TRN,AC_WRAP,9,9,AC_TRN,AC_WRAP,8,3,AC_TRN,AC_WRAP>:for -UNROLL yes 39 | directive set /EdgeDetect_SinglePort/verticalDerivative/core/line_buf0:rsc -MAP_TO_MODULE ccs_sample_mem.ccs_ram_sync_singleport 40 | directive set /EdgeDetect_SinglePort/verticalDerivative/core/line_buf1:rsc -MAP_TO_MODULE ccs_sample_mem.ccs_ram_sync_singleport 41 | 42 | go architect 43 | go allocate 44 | go extract 45 | 46 | -------------------------------------------------------------------------------- /WalkThroughs/EdgeDetect/src/EdgeDetect_SinglePort_Programable.h: -------------------------------------------------------------------------------- 1 | /************************************************************************** 2 | * * 3 | * Edge Detect Design Walkthrough for HLS * 4 | * * 5 | * Software Version: 1.0 * 6 | * * 7 | * Release Date : Tue Jan 14 15:40:43 PST 2020 * 8 | * Release Type : Production Release * 9 | * Release Build : 1.0.0 * 10 | * * 11 | * Copyright 2020, Mentor Graphics Corporation, * 12 | * * 13 | * All Rights Reserved. * 14 | * 15 | ************************************************************************** 16 | * Licensed under the Apache License, Version 2.0 (the "License"); * 17 | * you may not use this file except in compliance with the License. * 18 | * You may obtain a copy of the License at * 19 | * * 20 | * http://www.apache.org/licenses/LICENSE-2.0 * 21 | * * 22 | * Unless required by applicable law or agreed to in writing, software * 23 | * distributed under the License is distributed on an "AS IS" BASIS, * 24 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or * 25 | * implied. * 26 | * See the License for the specific language governing permissions and * 27 | * limitations under the License. * 28 | ************************************************************************** 29 | * * 30 | * The most recent version of this package is available at github. * 31 | * * 32 | *************************************************************************/ 33 | #ifndef _INCLUDED_EDGEDETECT_SINGLEPORT_H_ 34 | #define _INCLUDED_EDGEDETECT_SINGLEPORT_H_ 35 | 36 | // Revision History 37 | // Rev 1 - Coding of edge detection algorithm in C++ 38 | // Rev 2 - Converted to using bit-accurate data types 39 | // Calculated bit growth for internal variables 40 | // Quantized angle values for 5 fractional bits -pi to pi 41 | // Rev 3 - Switch to using HLSLIBS ac_math library for high performance 42 | // math functions. 43 | // Add support for verification using SCVerify 44 | // Rev 4 - Refinining memory architecture for 1PPC 45 | // Rev 5 - Modularized into hierarchy for performance 46 | // Rev 6 - Recode to use single-port memories 47 | // Rev 7 - Recode to make the design programmable for image size 48 | 49 | #include 50 | // This is Catapult's math library implementation, see docs for details 51 | #include 52 | #include 53 | 54 | // Class for fifo-style hierarchical interconnect objects 55 | #include 56 | 57 | // Include constant kernel definition 58 | #include "edge_defs.h" 59 | #include 60 | 61 | template 62 | class EdgeDetect_SinglePort 63 | { 64 | // Define some bit-accurate types to use in this model 65 | typedef uint8 pixelType; // input pixel is 0-255 66 | typedef uint16 pixelType2x; // two pixels packed 67 | typedef int9 gradType; // Derivative is max range -255 to 255 68 | typedef uint18 sqType; // Result of 9-bit x 9-bit 69 | typedef ac_fixed<19,19,false> sumType; // Result of 18-bit + 18-bit fixed pt integer for squareroot 70 | typedef uint9 magType; // 9-bit unsigned magnitute result 71 | typedef ac_fixed<8,3,true> angType; // 3 integer bit, 5 fractional bits for quantized angle -pi to pi 72 | 73 | // Static interconnect channels (FIFOs) between blocks 74 | ac_channel dy; 75 | ac_channel dx; 76 | ac_channel dat; // channel for passing input pixels to horizontalDerivative 77 | 78 | public: 79 | //Compute number of bits for max image size count, used internally and in testbench 80 | typedef ac_int::val,false> maxW; 81 | typedef ac_int::val,false> maxH; 82 | EdgeDetect_SinglePort() {} 83 | 84 | //-------------------------------------------------------------------------- 85 | // Function: run 86 | // Top interface for data in/out of class. Combines vertical and 87 | // horizontal derivative and magnitude/angle computation. 88 | #pragma hls_design interface 89 | void CCS_BLOCK(run)(ac_channel &dat_in, 90 | maxW &widthIn, 91 | maxH &heightIn, 92 | ac_channel &magn, 93 | ac_channel &angle) 94 | { 95 | verticalDerivative(dat_in, widthIn, heightIn, dat, dy); 96 | horizontalDerivative(dat, widthIn, heightIn, dx); 97 | magnitudeAngle(dx, dy, widthIn, heightIn, magn, angle); 98 | } 99 | 100 | private: 101 | //-------------------------------------------------------------------------- 102 | // Function: verticalDerivative 103 | // Compute the vertical derivative on the input data 104 | #pragma hls_design 105 | void verticalDerivative(ac_channel &dat_in, 106 | maxW &widthIn, 107 | maxH &heightIn, 108 | ac_channel &dat_out, 109 | ac_channel &dy) 110 | { 111 | // Line buffers store pixel line history - Mapped to RAM 112 | pixelType2x line_buf0[imageWidth/2]; 113 | pixelType2x line_buf1[imageWidth/2]; 114 | pixelType2x rdbuf0_pix, rdbuf1_pix; 115 | pixelType2x wrbuf0_pix, wrbuf1_pix; 116 | pixelType pix0, pix1, pix2; 117 | gradType pix; 118 | 119 | // Remove loop upperbounds for RTL code coverage 120 | // Use bit accurate data types on loop iterator 121 | VROW: for (maxH y = 0;; y++) { // One extra iteration to ramp-up window 122 | VCOL: for (maxW x = 0;; x++) { 123 | if (y <= imageHeight-1) { 124 | pix0 = dat_in.read(); // Read streaming interface 125 | } 126 | // Write data cache, write lower 8 on even iterations of COL loop, upper 8 on odd 127 | if ( (x&1) == 0 ) { 128 | wrbuf0_pix.set_slc(0,pix0); 129 | } else { 130 | wrbuf0_pix.set_slc(8,pix0); 131 | } 132 | // Read line buffers into read buffer caches on even iterations of COL loop 133 | if ( (x&1) == 0 ) { 134 | // vertical window of pixels 135 | rdbuf1_pix = line_buf1[x/2]; 136 | rdbuf0_pix = line_buf0[x/2]; 137 | } else { // Write line buffer caches on odd iterations of COL loop 138 | line_buf1[x/2] = rdbuf0_pix; // copy previous line 139 | line_buf0[x/2] = wrbuf0_pix; // store current line 140 | } 141 | // Get 8-bit data from read buffer caches, lower 8 on even iterations of COL loop 142 | pix2 = ((x&1)==0) ? rdbuf1_pix.slc<8>(0) : rdbuf1_pix.slc<8>(8); 143 | pix1 = ((x&1)==0) ? rdbuf0_pix.slc<8>(0) : rdbuf0_pix.slc<8>(8); 144 | 145 | // Boundary condition processing 146 | if (y == 1) { 147 | pix2 = pix1; // top boundary (replicate pix1 up to pix2) 148 | } 149 | if (y == imageHeight) { 150 | pix0 = pix1; // bottom boundary (replicate pix1 down to pix0) 151 | } 152 | 153 | // Calculate derivative 154 | pix = pix2*kernel[0] + pix1*kernel[1] + pix0*kernel[2]; 155 | 156 | if (y != 0) { // Write streaming interfaces 157 | dat_out.write(pix1); // Pass thru original data 158 | dy.write(pix); // derivative output 159 | } 160 | // programmable width exit condition 161 | if (x == maxW(widthIn-1)) // cast to maxW for RTL code coverage 162 | break; 163 | } 164 | //programmable height exit condition 165 | if (y == heightIn) 166 | break; 167 | } 168 | } 169 | 170 | //-------------------------------------------------------------------------- 171 | // Function: horizontalDerivative 172 | // Compute the horizontal derivative on the input data 173 | #pragma hls_design 174 | void horizontalDerivative(ac_channel &dat_in, 175 | maxW &widthIn, 176 | maxH &heightIn, 177 | ac_channel &dx) 178 | { 179 | // pixel buffers store pixel history 180 | pixelType pix_buf0; 181 | pixelType pix_buf1; 182 | 183 | pixelType pix0 = 0; 184 | pixelType pix1 = 0; 185 | pixelType pix2 = 0; 186 | 187 | gradType pix; 188 | 189 | HROW: for (maxH y = 0; ; y++) { 190 | HCOL: for (maxW x = 0; ; x++) { // One extra iteration to ramp-up window 191 | pix2 = pix_buf1; 192 | pix1 = pix_buf0; 193 | if (x <= imageWidth-1) { 194 | pix0 = dat_in.read(); // Read streaming interface 195 | } 196 | if (x == 1) { 197 | pix2 = pix1; // left boundary condition (replicate pix1 left to pix2) 198 | } 199 | if (x == imageWidth) { 200 | pix0 = pix1; // right boundary condition (replicate pix1 right to pix0) 201 | } 202 | 203 | pix_buf1 = pix_buf0; 204 | pix_buf0 = pix0; 205 | // Calculate derivative 206 | pix = pix2*kernel[0] + pix1*kernel[1] + pix0*kernel[2]; 207 | 208 | if (x != 0) { // Write streaming interface 209 | dx.write(pix); // derivative out 210 | } 211 | // programmable width exit condition 212 | if ( x == widthIn) 213 | break; 214 | } 215 | // programmable height exit condition 216 | if (y == maxH(heightIn-1)) // cast to maxH for RTL code coverage 217 | break; 218 | } 219 | } 220 | 221 | //-------------------------------------------------------------------------- 222 | // Function: magnitudeAngle 223 | // Compute the magnitute and angle based on the horizontal and vertical 224 | // derivative results 225 | #pragma hls_design 226 | void magnitudeAngle(ac_channel &dx_in, 227 | ac_channel &dy_in, 228 | maxW &widthIn, 229 | maxH &heightIn, 230 | ac_channel &magn, 231 | ac_channel &angle) 232 | { 233 | gradType dx, dy; 234 | sqType dx_sq; 235 | sqType dy_sq; 236 | sumType sum; // fixed point integer for sqrt 237 | angType at; 238 | ac_fixed<16,9,false> sq_rt; // square-root return type 239 | 240 | MROW: for (maxH y = 0; ; y++) { 241 | MCOL: for (maxW x = 0; ; x++) { 242 | dx = dx_in.read(); 243 | dy = dy_in.read(); 244 | dx_sq = dx * dx; 245 | dy_sq = dy * dy; 246 | sum = dx_sq + dy_sq; 247 | // Catapult's math library piecewise linear implementation of sqrt and atan2 248 | ac_math::ac_sqrt_pwl(sum,sq_rt); 249 | magn.write(sq_rt.to_uint()); 250 | ac_math::ac_atan2_cordic((ac_fixed<9,9>)dy, (ac_fixed<9,9>) dx, at); 251 | angle.write(at); 252 | // programmable width exit condition 253 | if (x == maxW(widthIn-1)) // cast to maxW for RTL code coverage 254 | break; 255 | } 256 | // programmable height exit condition 257 | if (y == maxH(heightIn-1)) // cast to maxH for RTL code coverage 258 | break; 259 | } 260 | } 261 | 262 | }; 263 | 264 | #endif 265 | 266 | -------------------------------------------------------------------------------- /WalkThroughs/EdgeDetect/src/EdgeDetect_SinglePort_Programable.tcl: -------------------------------------------------------------------------------- 1 | #------------------------------------------------------------ 2 | # Sliding Window Walkthrough - Singleport Mem and programmable image size 3 | #------------------------------------------------------------ 4 | 5 | # Establish the location of this script and use it to reference all 6 | # other files in this example 7 | set sfd [file dirname [info script]] 8 | 9 | # Reset the options to the factory defaults 10 | options defaults 11 | options set /Input/CppStandard c++11 12 | 13 | project new 14 | 15 | flow package require /SCVerify 16 | flow package option set /SCVerify/USE_CCS_BLOCK true 17 | flow package option set /SCVerify/INVOKE_ARGS "[file join $sfd image people_gray.bmp] out_algorithm.bmp out_hw.bmp" 18 | 19 | solution file add {$MGC_HOME/shared/include/bmpUtil/bmp_io.cpp} -type C++ -exclude true 20 | solution file add [file join $sfd EdgeDetect_SinglePort_Programable_tb.cpp] -type C++ 21 | 22 | go analyze 23 | directive set -DESIGN_HIERARCHY {{EdgeDetect_SinglePort<1296, 864>} {EdgeDetect_SinglePort<1296, 864>::verticalDerivative} {EdgeDetect_SinglePort<1296, 864>::horizontalDerivative} {EdgeDetect_SinglePort<1296, 864>::magnitudeAngle}} 24 | go compile 25 | solution library add nangate-45nm_beh -file {$MGC_HOME/pkgs/siflibs/nangate/nangate-45nm_beh.lib} -- -rtlsyntool OasysRTL 26 | solution library add ccs_sample_mem -file {$MGC_HOME/pkgs/siflibs/ccs_sample_mem.lib} 27 | go libraries 28 | directive set -CLOCKS {clk {-CLOCK_PERIOD 3.33 -CLOCK_EDGE rising -CLOCK_UNCERTAINTY 0.0 -CLOCK_HIGH_TIME 1.665 -RESET_SYNC_NAME rst -RESET_ASYNC_NAME arst_n -RESET_KIND sync -RESET_SYNC_ACTIVE high -RESET_ASYNC_ACTIVE low -ENABLE_ACTIVE high}} 29 | go assembly 30 | 31 | directive set /EdgeDetect_SinglePort<1296,864>/verticalDerivative/core/VROW -PIPELINE_INIT_INTERVAL 1 32 | directive set /EdgeDetect_SinglePort<1296,864>/horizontalDerivative/core/HROW -PIPELINE_INIT_INTERVAL 1 33 | directive set /EdgeDetect_SinglePort<1296,864>/magnitudeAngle/core/MROW -PIPELINE_INIT_INTERVAL 1 34 | directive set /EdgeDetect_SinglePort<1296,864>/magnitudeAngle/core/ac_math::ac_atan2_cordic<9,9,AC_TRN,AC_WRAP,9,9,AC_TRN,AC_WRAP,8,3,AC_TRN,AC_WRAP>:for -UNROLL yes 35 | directive set /EdgeDetect_SinglePort<1296,864>/widthIn:rsc -MAP_TO_MODULE {[DirectInput]} 36 | directive set /EdgeDetect_SinglePort<1296,864>/heightIn:rsc -MAP_TO_MODULE {[DirectInput]} 37 | go architect 38 | go extract 39 | -------------------------------------------------------------------------------- /WalkThroughs/EdgeDetect/src/EdgeDetect_SinglePort_Programable_tb.cpp: -------------------------------------------------------------------------------- 1 | /************************************************************************** 2 | * * 3 | * Edge Detect Design Walkthrough for HLS * 4 | * * 5 | * Software Version: 1.0 * 6 | * * 7 | * Release Date : Tue Jan 14 15:40:43 PST 2020 * 8 | * Release Type : Production Release * 9 | * Release Build : 1.0.0 * 10 | * * 11 | * Copyright 2020, Mentor Graphics Corporation, * 12 | * * 13 | * All Rights Reserved. * 14 | * 15 | ************************************************************************** 16 | * Licensed under the Apache License, Version 2.0 (the "License"); * 17 | * you may not use this file except in compliance with the License. * 18 | * You may obtain a copy of the License at * 19 | * * 20 | * http://www.apache.org/licenses/LICENSE-2.0 * 21 | * * 22 | * Unless required by applicable law or agreed to in writing, software * 23 | * distributed under the License is distributed on an "AS IS" BASIS, * 24 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or * 25 | * implied. * 26 | * See the License for the specific language governing permissions and * 27 | * limitations under the License. * 28 | ************************************************************************** 29 | * * 30 | * The most recent version of this package is available at github. * 31 | * * 32 | *************************************************************************/ 33 | #include 34 | #include 35 | 36 | using namespace std; 37 | 38 | #include "EdgeDetect_Algorithm.h" 39 | #include "EdgeDetect_SinglePort_Programable.h" 40 | 41 | #include "bmpUtil/bmp_io.hpp" 42 | #include 43 | #include 44 | #include 45 | #include 46 | #include 47 | 48 | CCS_MAIN(int argc, char *argv[]) 49 | { 50 | const int iW = 1296; 51 | const int iH = 864; 52 | EdgeDetect_Algorithm inst0; 53 | EdgeDetect_SinglePort inst1; 54 | 55 | unsigned long int width = iW; 56 | long int height = iH; 57 | 58 | 59 | EdgeDetect_SinglePort::maxW widthIn = iW; 60 | #ifndef POWER 61 | EdgeDetect_SinglePort::maxH heightIn = iH; 62 | #else 63 | EdgeDetect_SinglePort::maxH heightIn = 30;//use less rows for power analysis 64 | #endif 65 | unsigned char *rarray = new unsigned char[iH*iW]; 66 | unsigned char *garray = new unsigned char[iH*iW]; 67 | unsigned char *barray = new unsigned char[iH*iW]; 68 | 69 | cout << "Loading Input File" << endl; 70 | 71 | if (argc < 3) { 72 | cout << "Usage: " << argv[0] << " " << endl; 73 | CCS_RETURN(-1); 74 | } 75 | 76 | std::string bmpIn(argv[1]); // input bitmap file 77 | std::string bmpAlg(argv[2]); // output bitmap (algorithm) 78 | std::string bmpBA(argv[3]); // output bitmap (bit-accurate) 79 | 80 | bmp_read((char*)bmpIn.c_str(), &width, &height, &rarray, &garray, &barray); 81 | assert(width==iW); 82 | assert(height==iH); 83 | 84 | #ifdef DEBUG 85 | std::string cmd; 86 | cmd = "display "; 87 | cmd.append(bmpIn.c_str()); 88 | std::cout << "Display input image file using command: " << cmd << endl; 89 | std::system(cmd.c_str()); 90 | #endif 91 | 92 | ac_channel dat_in; 93 | ac_channel magn; 94 | ac_channel > angle; 95 | 96 | unsigned char *dat_in_orig = new unsigned char[iH*iW];; 97 | double *magn_orig = new double[iH*iW]; 98 | double *angle_orig = new double[iH*iW]; 99 | 100 | unsigned cnt = 0; 101 | for (int y = 0; y < iH; y++) { 102 | for (int x = 0; x < iW; x++) { 103 | dat_in.write(rarray[cnt]); // just using red component (pseudo monochrome) 104 | dat_in_orig[cnt] = rarray[cnt]; 105 | cnt++; 106 | } 107 | } 108 | 109 | cout << "Running" << endl; 110 | 111 | inst0.run(dat_in_orig,magn_orig,angle_orig); 112 | inst1.run(dat_in,widthIn,heightIn,magn,angle); 113 | 114 | cnt = 0; 115 | float sumErr = 0; 116 | float sumAngErr = 0; 117 | for (int y = 0; y < heightIn; y++) { 118 | for (int x = 0; x < iW; x++) { 119 | int hw = magn.read(); 120 | int alg = (int)*(magn_orig+cnt); 121 | int diff = alg-hw; 122 | int adiff = abs(diff); 123 | sumErr += adiff; 124 | float angO = (double)*(angle_orig+cnt); 125 | float angHw = angle.read().to_double(); 126 | float angAdiff = abs(angO-angHw); 127 | sumAngErr += angAdiff; 128 | cnt++; 129 | rarray[cnt] = hw; // repurposing 'red' array to the bit-accurate monochrome edge-detect output 130 | garray[cnt] = alg; // repurposing 'green' array to the original algorithmic edge-detect output 131 | } 132 | } 133 | 134 | printf("Magnitude: Manhattan norm per pixel %f\n",sumErr/(iH*iW)); 135 | printf("Angle: Manhattan norm per pixel %f\n",sumAngErr/(iH*iW)); 136 | 137 | cout << "Writing algorithmic bitmap output to: " << bmpAlg << endl; 138 | bmp_24_write((char*)bmpAlg.c_str(), iW, iH, garray, garray, garray); 139 | 140 | #ifdef DEBUG 141 | cmd = "display "; 142 | cmd.append(bmpAlg.c_str()); 143 | std::cout << "Display output image file using command: " << cmd << endl; 144 | std::system(cmd.c_str()); 145 | #endif 146 | 147 | cout << "Writing bit-accurate bitmap output to: " << bmpBA << endl; 148 | bmp_24_write((char*)bmpBA.c_str(), iW, iH, rarray, rarray, rarray); 149 | 150 | #ifdef DEBUG 151 | cmd = "display "; 152 | cmd.append(bmpBA.c_str()); 153 | std::cout << "Display output image file using command: " << cmd << endl; 154 | std::system(cmd.c_str()); 155 | #endif 156 | 157 | delete (dat_in_orig); 158 | delete (magn_orig); 159 | delete (angle_orig); 160 | delete (rarray); 161 | delete (garray); 162 | delete (barray); 163 | 164 | cout << "Finished" << endl; 165 | 166 | CCS_RETURN(0); 167 | } 168 | -------------------------------------------------------------------------------- /WalkThroughs/EdgeDetect/src/EdgeDetect_SinglePort_tb.cpp: -------------------------------------------------------------------------------- 1 | /************************************************************************** 2 | * * 3 | * Edge Detect Design Walkthrough for HLS * 4 | * * 5 | * Software Version: 1.0 * 6 | * * 7 | * Release Date : Tue Jan 14 15:40:43 PST 2020 * 8 | * Release Type : Production Release * 9 | * Release Build : 1.0.0 * 10 | * * 11 | * Copyright 2020, Mentor Graphics Corporation, * 12 | * * 13 | * All Rights Reserved. * 14 | * 15 | ************************************************************************** 16 | * Licensed under the Apache License, Version 2.0 (the "License"); * 17 | * you may not use this file except in compliance with the License. * 18 | * You may obtain a copy of the License at * 19 | * * 20 | * http://www.apache.org/licenses/LICENSE-2.0 * 21 | * * 22 | * Unless required by applicable law or agreed to in writing, software * 23 | * distributed under the License is distributed on an "AS IS" BASIS, * 24 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or * 25 | * implied. * 26 | * See the License for the specific language governing permissions and * 27 | * limitations under the License. * 28 | ************************************************************************** 29 | * * 30 | * The most recent version of this package is available at github. * 31 | * * 32 | *************************************************************************/ 33 | #include 34 | #include 35 | 36 | using namespace std; 37 | 38 | #include "EdgeDetect_Algorithm.h" 39 | #include "EdgeDetect_SinglePort.h" 40 | 41 | #include "bmpUtil/bmp_io.hpp" 42 | #include 43 | #include 44 | #include 45 | #include 46 | #include 47 | 48 | CCS_MAIN(int argc, char *argv[]) 49 | { 50 | const int iW = 1296; 51 | const int iH = 864; 52 | EdgeDetect_Algorithm inst0; 53 | EdgeDetect_SinglePort inst1; 54 | 55 | unsigned long int width = iW; 56 | long int height = iH; 57 | unsigned char *rarray = new unsigned char[iH*iW]; 58 | unsigned char *garray = new unsigned char[iH*iW]; 59 | unsigned char *barray = new unsigned char[iH*iW]; 60 | 61 | cout << "Loading Input File" << endl; 62 | 63 | if (argc < 3) { 64 | cout << "Usage: " << argv[0] << " " << endl; 65 | CCS_RETURN(-1); 66 | } 67 | 68 | std::string bmpIn(argv[1]); // input bitmap file 69 | std::string bmpAlg(argv[2]); // output bitmap (algorithm) 70 | std::string bmpBA(argv[3]); // output bitmap (bit-accurate) 71 | 72 | bmp_read((char*)bmpIn.c_str(), &width, &height, &rarray, &garray, &barray); 73 | assert(width==iW); 74 | assert(height==iH); 75 | 76 | #ifdef DEBUG 77 | std::string cmd; 78 | cmd = "display "; 79 | cmd.append(bmpIn.c_str()); 80 | std::cout << "Display input image file using command: " << cmd << endl; 81 | std::system(cmd.c_str()); 82 | #endif 83 | 84 | ac_channel dat_in; 85 | ac_channel magn; 86 | ac_channel > angle; 87 | 88 | unsigned char *dat_in_orig = new unsigned char[iH*iW];; 89 | double *magn_orig = new double[iH*iW]; 90 | double *angle_orig = new double[iH*iW]; 91 | 92 | unsigned cnt = 0; 93 | for (int y = 0; y < iH; y++) { 94 | for (int x = 0; x < iW; x++) { 95 | dat_in.write(rarray[cnt]); // just using red component (pseudo monochrome) 96 | dat_in_orig[cnt] = rarray[cnt]; 97 | cnt++; 98 | } 99 | } 100 | 101 | cout << "Running" << endl; 102 | 103 | inst0.run(dat_in_orig,magn_orig,angle_orig); 104 | inst1.run(dat_in,magn,angle); 105 | 106 | cnt = 0; 107 | float sumErr = 0; 108 | float sumAngErr = 0; 109 | for (int y = 0; y < iH; y++) { 110 | for (int x = 0; x < iW; x++) { 111 | int hw = magn.read(); 112 | int alg = (int)*(magn_orig+cnt); 113 | int diff = alg-hw; 114 | int adiff = abs(diff); 115 | sumErr += adiff; 116 | float angO = (double)*(angle_orig+cnt); 117 | float angHw = angle.read().to_double(); 118 | float angAdiff = abs(angO-angHw); 119 | sumAngErr += angAdiff; 120 | cnt++; 121 | rarray[cnt] = hw; // repurposing 'red' array to the bit-accurate monochrome edge-detect output 122 | garray[cnt] = alg; // repurposing 'green' array to the original algorithmic edge-detect output 123 | } 124 | } 125 | 126 | printf("Magnitude: Manhattan norm per pixel %f\n",sumErr/(iH*iW)); 127 | printf("Angle: Manhattan norm per pixel %f\n",sumAngErr/(iH*iW)); 128 | 129 | cout << "Writing algorithmic bitmap output to: " << bmpAlg << endl; 130 | bmp_24_write((char*)bmpAlg.c_str(), iW, iH, garray, garray, garray); 131 | 132 | #ifdef DEBUG 133 | cmd = "display "; 134 | cmd.append(bmpAlg.c_str()); 135 | std::cout << "Display output image file using command: " << cmd << endl; 136 | std::system(cmd.c_str()); 137 | #endif 138 | 139 | cout << "Writing bit-accurate bitmap output to: " << bmpBA << endl; 140 | bmp_24_write((char*)bmpBA.c_str(), iW, iH, rarray, rarray, rarray); 141 | 142 | #ifdef DEBUG 143 | cmd = "display "; 144 | cmd.append(bmpBA.c_str()); 145 | std::cout << "Display output image file using command: " << cmd << endl; 146 | std::system(cmd.c_str()); 147 | #endif 148 | 149 | delete (dat_in_orig); 150 | delete (magn_orig); 151 | delete (angle_orig); 152 | delete (rarray); 153 | delete (garray); 154 | delete (barray); 155 | 156 | cout << "Finished" << endl; 157 | 158 | CCS_RETURN(0); 159 | } 160 | -------------------------------------------------------------------------------- /WalkThroughs/EdgeDetect/src/EdgeDetect_Synthesizable.h: -------------------------------------------------------------------------------- 1 | /************************************************************************** 2 | * * 3 | * Edge Detect Design Walkthrough for HLS * 4 | * * 5 | * Software Version: 1.0 * 6 | * * 7 | * Release Date : Tue Jan 14 15:40:43 PST 2020 * 8 | * Release Type : Production Release * 9 | * Release Build : 1.0.0 * 10 | * * 11 | * Copyright 2020, Mentor Graphics Corporation, * 12 | * * 13 | * All Rights Reserved. * 14 | * 15 | ************************************************************************** 16 | * Licensed under the Apache License, Version 2.0 (the "License"); * 17 | * you may not use this file except in compliance with the License. * 18 | * You may obtain a copy of the License at * 19 | * * 20 | * http://www.apache.org/licenses/LICENSE-2.0 * 21 | * * 22 | * Unless required by applicable law or agreed to in writing, software * 23 | * distributed under the License is distributed on an "AS IS" BASIS, * 24 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or * 25 | * implied. * 26 | * See the License for the specific language governing permissions and * 27 | * limitations under the License. * 28 | ************************************************************************** 29 | * * 30 | * The most recent version of this package is available at github. * 31 | * * 32 | *************************************************************************/ 33 | #ifndef _INCLUDED_EDGEDETECT_SYNTHESIZABLE_H_ 34 | #define _INCLUDED_EDGEDETECT_SYNTHESIZABLE_H_ 35 | 36 | // Revision History 37 | // Rev 1 - Coding of edge detection algorithm in C++ 38 | // Rev 2 - Converted to using bit-accurate data types 39 | // Calculated bit growth for internal variables 40 | // Quantized angle values for 5 fractional bits -pi to pi 41 | // Rev 3 - Switch to using HLSLIBS ac_math library for high performance 42 | // math functions. 43 | // Add support for verification using SCVerify 44 | 45 | #include 46 | // This is Catapult's math library implementation, see docs for details 47 | #include 48 | #include 49 | 50 | // Include constant kernel definition 51 | #include "edge_defs.h" 52 | #include 53 | 54 | class EdgeDetect_Synthesizable 55 | { 56 | // Define some bit-accurate types to use in this model 57 | typedef uint8 pixelType; // input pixel is 0-255 58 | typedef int9 gradType; // Gradient is max range -255 to 255 59 | typedef uint18 sqType; // Result of 9-bit x 9-bit 60 | typedef ac_fixed<19,19,false> sumType; // Result of 18-bit + 18-bit fixed pt integer for squareroot 61 | typedef uint9 magType; // 9-bit unsigned magnitute result 62 | typedef ac_fixed<8,3,true> angType; // 3 integer bit, 5 fractional bits for quantized angle -pi to pi 63 | 64 | // Define some "constants" for use in algorithm 65 | enum { 66 | imageWidth = 1296, 67 | imageHeight = 864 68 | }; 69 | 70 | public: 71 | // Constructor 72 | EdgeDetect_Synthesizable() {} 73 | 74 | //-------------------------------------------------------------------------- 75 | // Function: run 76 | // Top interface for data in/out of class. Combines vertical and 77 | // horizontal derivative and magnitude/angle computation. 78 | #pragma hls_design interface 79 | void CCS_BLOCK(run)(pixelType dat_in[imageHeight][imageWidth], 80 | magType magn[imageHeight][imageWidth], 81 | angType angle[imageHeight][imageWidth]) 82 | { 83 | // allocate buffers for image data 84 | gradType dx[imageHeight][imageWidth]; 85 | gradType dy[imageHeight][imageWidth]; 86 | 87 | verticalDerivative(dat_in, dy); 88 | horizontalDerivative(dat_in, dx); 89 | magnitudeAngle(dx, dy, magn, angle); 90 | } 91 | 92 | //-------------------------------------------------------------------------- 93 | // Function: verticalDerivative 94 | // Compute the vertical derivative on the input data 95 | void verticalDerivative(pixelType dat_in[imageHeight][imageWidth], 96 | gradType dy[imageHeight][imageWidth]) 97 | { 98 | VROW: for (int y = 0; y < imageHeight; y++) { 99 | VCOL: for (int x = 0; x < imageWidth; x++) { 100 | dy[y][x] = 101 | dat_in[clip(y - 1, imageHeight-1)][x] * kernel[0] + 102 | dat_in[y][x] * kernel[1] + 103 | dat_in[clip(y + 1, imageHeight-1)][x] * kernel[2]; 104 | } 105 | } 106 | } 107 | 108 | //-------------------------------------------------------------------------- 109 | // Function: horizontalDerivative 110 | // Compute the horizontal derivative on the input data 111 | void horizontalDerivative(pixelType dat_in[imageHeight][imageWidth], 112 | gradType dx[imageHeight][imageWidth]) 113 | { 114 | HROW: for (int y = 0; y < imageHeight; y++) { 115 | HCOL: for (int x = 0; x < imageWidth; x++) { 116 | dx[y][x] = 117 | dat_in[y][clip(x - 1, imageWidth-1)] * kernel[0] + 118 | dat_in[y][x] * kernel[1] + 119 | dat_in[y][clip(x + 1, imageWidth-1)] * kernel[2]; 120 | } 121 | } 122 | } 123 | 124 | //-------------------------------------------------------------------------- 125 | // Function: magnitudeAngle 126 | // Compute the magnitute and angle based on the horizontal and vertical 127 | // derivative results 128 | void magnitudeAngle(gradType dx[imageHeight][imageWidth], 129 | gradType dy[imageHeight][imageWidth], 130 | magType magn[imageHeight][imageWidth], 131 | angType angle[imageHeight][imageWidth]) 132 | { 133 | sqType dx_sq; 134 | sqType dy_sq; 135 | sumType sum; // fixed point integer for sqrt 136 | angType at; 137 | ac_fixed<16,9,false> sq_rt; // square-root return type 138 | 139 | MROW: for (int y = 0; y < imageHeight; y++) { 140 | MCOL: for (int x = 0; x < imageWidth; x++) { 141 | dx_sq = dx[y][x] * dx[y][x]; 142 | dy_sq = dy[y][x] * dy[y][x]; 143 | sum = dx_sq + dy_sq; 144 | // Catapult's math library piecewise linear implementation of sqrt and atan2 145 | ac_math::ac_sqrt_pwl(sum,sq_rt); 146 | magn[y][x] = sq_rt.to_uint(); 147 | ac_math::ac_atan2_cordic((ac_fixed<9,9>) (dy[y][x]), (ac_fixed<9,9>) (dx[y][x]), at); 148 | angle[y][x] = at; 149 | } 150 | } 151 | } 152 | 153 | private: // Helper functions 154 | 155 | //-------------------------------------------------------------------------- 156 | // Function: clip 157 | // Perform boundary processing by "adjusting" the index value to "clip" 158 | // at either end 159 | int clip(int i, int bound) { 160 | if (i < 0) { 161 | return 0; // clip to the top/left value 162 | } else if (i >= bound) { 163 | return bound; // clip to the bottom/right value 164 | } else { 165 | return i; // return all others untouched 166 | } 167 | } 168 | 169 | //-------------------------------------------------------------------------- 170 | // Function: myPrint 171 | void myPrint(char a[]) { 172 | #ifndef __SYNTHESIS__ 173 | printf("%s\n",a); 174 | #endif 175 | } 176 | 177 | }; 178 | 179 | #endif 180 | 181 | -------------------------------------------------------------------------------- /WalkThroughs/EdgeDetect/src/EdgeDetect_Synthesizable.tcl: -------------------------------------------------------------------------------- 1 | #------------------------------------------------------------ 2 | # Sliding Window Walkthrough - Synthesizable 3 | #------------------------------------------------------------ 4 | 5 | # Establish the location of this script and use it to reference all 6 | # other files in this example 7 | set sfd [file dirname [info script]] 8 | 9 | # Reset the options to the factory defaults 10 | options defaults 11 | options set /Input/CppStandard c++11 12 | 13 | project new 14 | 15 | flow package require /SCVerify 16 | flow package option set /SCVerify/USE_CCS_BLOCK true 17 | flow package option set /SCVerify/INVOKE_ARGS "[file join $sfd image people_gray.bmp] out_algorithm.bmp out_hw.bmp" 18 | 19 | solution file add [file join $sfd EdgeDetect_Synthesizable_tb.cpp] -type C++ 20 | solution file add {$MGC_HOME/shared/include/bmpUtil/bmp_io.cpp} -type C++ -exclude true 21 | 22 | go analyze 23 | directive set -DESIGN_HIERARCHY EdgeDetect_Synthesizable 24 | go compile 25 | 26 | directive set /EdgeDetect_Synthesizable/run -DESIGN_GOAL Latency 27 | 28 | solution library add nangate-45nm_beh -file {$MGC_HOME/pkgs/siflibs/nangate/nangate-45nm_beh.lib} -- -rtlsyntool OasysRTL 29 | solution library add ccs_sample_mem -file {$MGC_HOME/pkgs/siflibs/ccs_sample_mem.lib} 30 | 31 | go libraries 32 | directive set -CLOCKS {clk {-CLOCK_PERIOD 3.33 -CLOCK_EDGE rising -CLOCK_UNCERTAINTY 0.0 -CLOCK_HIGH_TIME 1.665 -RESET_SYNC_NAME rst -RESET_ASYNC_NAME arst_n -RESET_KIND sync -RESET_SYNC_ACTIVE high -RESET_ASYNC_ACTIVE low -ENABLE_ACTIVE high}} 33 | go assembly 34 | 35 | directive set /EdgeDetect_Synthesizable/run/VROW -MERGEABLE false 36 | directive set /EdgeDetect_Synthesizable/run/VCOL -MERGEABLE false 37 | directive set /EdgeDetect_Synthesizable/run/HROW -MERGEABLE false 38 | directive set /EdgeDetect_Synthesizable/run/HCOL -MERGEABLE false 39 | directive set /EdgeDetect_Synthesizable/run/MROW -MERGEABLE false 40 | directive set /EdgeDetect_Synthesizable/run/MCOL -MERGEABLE false 41 | directive set /EdgeDetect_Synthesizable/run/ac_math::ac_atan2_cordic<9,9,AC_TRN,AC_WRAP,9,9,AC_TRN,AC_WRAP,8,3,AC_TRN,AC_WRAP>:for -MERGEABLE false 42 | go architect 43 | go extract 44 | 45 | -------------------------------------------------------------------------------- /WalkThroughs/EdgeDetect/src/EdgeDetect_Synthesizable_tb.cpp: -------------------------------------------------------------------------------- 1 | /************************************************************************** 2 | * * 3 | * Edge Detect Design Walkthrough for HLS * 4 | * * 5 | * Software Version: 1.0 * 6 | * * 7 | * Release Date : Tue Jan 14 15:40:43 PST 2020 * 8 | * Release Type : Production Release * 9 | * Release Build : 1.0.0 * 10 | * * 11 | * Copyright 2020, Mentor Graphics Corporation, * 12 | * * 13 | * All Rights Reserved. * 14 | * 15 | ************************************************************************** 16 | * Licensed under the Apache License, Version 2.0 (the "License"); * 17 | * you may not use this file except in compliance with the License. * 18 | * You may obtain a copy of the License at * 19 | * * 20 | * http://www.apache.org/licenses/LICENSE-2.0 * 21 | * * 22 | * Unless required by applicable law or agreed to in writing, software * 23 | * distributed under the License is distributed on an "AS IS" BASIS, * 24 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or * 25 | * implied. * 26 | * See the License for the specific language governing permissions and * 27 | * limitations under the License. * 28 | ************************************************************************** 29 | * * 30 | * The most recent version of this package is available at github. * 31 | * * 32 | *************************************************************************/ 33 | #include 34 | #include 35 | 36 | using namespace std; 37 | 38 | #include "EdgeDetect_Algorithm.h" 39 | #include "EdgeDetect_Synthesizable.h" 40 | 41 | #include "bmpUtil/bmp_io.hpp" 42 | #include 43 | #include 44 | #include 45 | #include 46 | #include 47 | 48 | CCS_MAIN(int argc, char *argv[]) 49 | { 50 | const int iW = 1296; 51 | const int iH = 864; 52 | EdgeDetect_Algorithm inst0; 53 | EdgeDetect_Synthesizable inst1; 54 | 55 | unsigned long int width = iW; 56 | long int height = iH; 57 | unsigned char *rarray = new unsigned char[iH*iW]; 58 | unsigned char *garray = new unsigned char[iH*iW]; 59 | unsigned char *barray = new unsigned char[iH*iW]; 60 | 61 | cout << "Loading Input File" << endl; 62 | 63 | if (argc < 3) { 64 | cout << "Usage: " << argv[0] << " " << endl; 65 | CCS_RETURN(-1); 66 | } 67 | 68 | std::string bmpIn(argv[1]); // input bitmap file 69 | std::string bmpAlg(argv[2]); // output bitmap (algorithm) 70 | std::string bmpBA(argv[3]); // output bitmap (bit-accurate) 71 | 72 | bmp_read((char*)bmpIn.c_str(), &width, &height, &rarray, &garray, &barray); 73 | assert(width==iW); 74 | assert(height==iH); 75 | 76 | #ifdef DEBUG 77 | std::string cmd; 78 | cmd = "display "; 79 | cmd.append(bmpIn.c_str()); 80 | std::cout << "Display input image file using command: " << cmd << endl; 81 | std::system(cmd.c_str()); 82 | #endif 83 | 84 | typedef uint8 (array_uint8)[iW]; 85 | array_uint8 *dat_in = new uint8[iH][iW]; 86 | 87 | typedef uint9 (array_uint9)[iW]; 88 | array_uint9 *magn = new uint9[iH][iW]; 89 | 90 | typedef ac_fixed<8,3> (array_af83)[iW]; 91 | array_af83 *angle = new ac_fixed<8,3>[iH][iW]; 92 | 93 | unsigned char *dat_in_orig = new unsigned char[iH*iW];; 94 | double *magn_orig = new double[iH*iW]; 95 | double *angle_orig = new double[iH*iW]; 96 | 97 | unsigned cnt = 0; 98 | for (int y = 0; y < iH; y++) { 99 | for (int x = 0; x < iW; x++) { 100 | dat_in[y][x] = rarray[cnt]; // just using red component (pseudo monochrome) 101 | dat_in_orig[cnt] = rarray[cnt]; 102 | cnt++; 103 | } 104 | } 105 | 106 | cout << "Running" << endl; 107 | 108 | inst0.run(dat_in_orig,magn_orig,angle_orig); 109 | inst1.run(dat_in,magn,angle); 110 | 111 | cnt = 0; 112 | float sumErr = 0; 113 | float sumAngErr = 0; 114 | for (int y = 0; y < iH; y++) { 115 | for (int x = 0; x < iW; x++) { 116 | int hw = magn[y][x]; 117 | int alg = (int)*(magn_orig+cnt); 118 | int diff = alg-hw; 119 | int adiff = abs(diff); 120 | sumErr += adiff; 121 | float angO = (double)*(angle_orig+cnt); 122 | float angHw = angle[y][x].to_double(); 123 | float angAdiff = abs(angO-angHw); 124 | sumAngErr += angAdiff; 125 | cnt++; 126 | rarray[cnt] = hw; // repurposing 'red' array to the bit-accurate monochrome edge-detect output 127 | garray[cnt] = alg; // repurposing 'green' array to the original algorithmic edge-detect output 128 | } 129 | } 130 | 131 | printf("Magnitude: Manhattan norm per pixel %f\n",sumErr/(iH*iW)); 132 | printf("Angle: Manhattan norm per pixel %f\n",sumAngErr/(iH*iW)); 133 | 134 | cout << "Writing algorithmic bitmap output to: " << bmpAlg << endl; 135 | bmp_24_write((char*)bmpAlg.c_str(), iW, iH, garray, garray, garray); 136 | 137 | #ifdef DEBUG 138 | cmd = "display "; 139 | cmd.append(bmpAlg.c_str()); 140 | std::cout << "Display output image file using command: " << cmd << endl; 141 | std::system(cmd.c_str()); 142 | #endif 143 | 144 | cout << "Writing bit-accurate bitmap output to: " << bmpBA << endl; 145 | bmp_24_write((char*)bmpBA.c_str(), iW, iH, rarray, rarray, rarray); 146 | 147 | #ifdef DEBUG 148 | cmd = "display "; 149 | cmd.append(bmpBA.c_str()); 150 | std::cout << "Display output image file using command: " << cmd << endl; 151 | std::system(cmd.c_str()); 152 | #endif 153 | 154 | delete (dat_in_orig); 155 | delete (magn_orig); 156 | delete (angle_orig); 157 | delete (dat_in); 158 | delete (magn); 159 | delete (angle); 160 | delete (rarray); 161 | delete (garray); 162 | delete (barray); 163 | 164 | cout << "Finished" << endl; 165 | 166 | CCS_RETURN(0); 167 | } 168 | -------------------------------------------------------------------------------- /WalkThroughs/EdgeDetect/src/Makefile: -------------------------------------------------------------------------------- 1 | 2 | # Set CATAPULT_HOME to point to your catapult install Mgc_home dir 3 | CATAPULT_HOME = /wv/hlsb/CATAPULT/10.3d/PRODUCTION/aol/Mgc_home 4 | 5 | # allow for str.c_str() to pass as char* 6 | CFLAGS += -g -std=c++11 7 | 8 | ba.exe: edge_defs.h EdgeDetect_Algorithm.h EdgeDetect_BitAccurate.h EdgeDetect_BitAccurate_tb.cpp 9 | -$(MGC_HOME)/bin/g++ $(CFLAGS) -I $(MGC_HOME)/shared/include $(MGC_HOME)/shared/include/bmpUtil/bmp_io.cpp EdgeDetect_BitAccurate_tb.cpp -o $@ 10 | ulimit -S -s 80000 && $@ image/people_gray.bmp orig1.bmp ba.bmp 11 | 12 | clean: 13 | rm -f EdgeDetect_BitAccurate_tb.exe *.bmp 14 | 15 | -------------------------------------------------------------------------------- /WalkThroughs/EdgeDetect/src/README.txt: -------------------------------------------------------------------------------- 1 | EdgeDetect_Algorithm.h - Original algorithm 2 | EdgeDetect_BitAccurate.h - Adding bit-accurate data types 3 | EdgeDetect_Synthesizable.h - Prepared for HLS 4 | EdgeDetect_MemoryArch.h - Refinining memory architecture for 1PPC 5 | EdgeDetect_Hierarchy.h - Modularized into hierarchy for performance 6 | EdgeDetect_SinglePort.h - Recode to use single-port memories 7 | EdgeDetect_SinglePort_Programable.h - Recode to make image size programable 8 | EdgeDetect_CircularBuf.h - Recode to have line buffers operate in a circular fasion for power reduction 9 | 10 | 11 | -------------------------------------------------------------------------------- /WalkThroughs/EdgeDetect/src/edge_defs.h: -------------------------------------------------------------------------------- 1 | /************************************************************************** 2 | * * 3 | * Edge Detect Design Walkthrough for HLS * 4 | * * 5 | * Software Version: 1.0 * 6 | * * 7 | * Release Date : Tue Jan 14 15:40:43 PST 2020 * 8 | * Release Type : Production Release * 9 | * Release Build : 1.0.0 * 10 | * * 11 | * Copyright 2020, Mentor Graphics Corporation, * 12 | * * 13 | * All Rights Reserved. * 14 | * 15 | ************************************************************************** 16 | * Licensed under the Apache License, Version 2.0 (the "License"); * 17 | * you may not use this file except in compliance with the License. * 18 | * You may obtain a copy of the License at * 19 | * * 20 | * http://www.apache.org/licenses/LICENSE-2.0 * 21 | * * 22 | * Unless required by applicable law or agreed to in writing, software * 23 | * distributed under the License is distributed on an "AS IS" BASIS, * 24 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or * 25 | * implied. * 26 | * See the License for the specific language governing permissions and * 27 | * limitations under the License. * 28 | ************************************************************************** 29 | * * 30 | * The most recent version of this package is available at github. * 31 | * * 32 | *************************************************************************/ 33 | #ifndef __EDGE_DEFS__ 34 | #define __EDGE_DEFS__ 35 | const int kernel[3] = {1, 0, -1}; 36 | #endif 37 | -------------------------------------------------------------------------------- /WalkThroughs/EdgeDetect/src/image/people_gray.bmp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hlslibs/hls_tutorials/80035b2a3fa964e46254b5d9c3c5e4ab268e6fcc/WalkThroughs/EdgeDetect/src/image/people_gray.bmp -------------------------------------------------------------------------------- /WalkThroughs/EdgeDetect/src/nangate-45nm_mem.lib: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hlslibs/hls_tutorials/80035b2a3fa964e46254b5d9c3c5e4ab268e6fcc/WalkThroughs/EdgeDetect/src/nangate-45nm_mem.lib -------------------------------------------------------------------------------- /WalkThroughs/EdgeDetect/src/ram_1k_16_sp.h: -------------------------------------------------------------------------------- 1 | /************************************************************************** 2 | * * 3 | * Edge Detect Design Walkthrough for HLS * 4 | * * 5 | * Software Version: 1.0 * 6 | * * 7 | * Release Date : Tue Jan 14 15:40:43 PST 2020 * 8 | * Release Type : Production Release * 9 | * Release Build : 1.0.0 * 10 | * * 11 | * Copyright 2020, Mentor Graphics Corporation, * 12 | * * 13 | * All Rights Reserved. * 14 | * 15 | ************************************************************************** 16 | * Licensed under the Apache License, Version 2.0 (the "License"); * 17 | * you may not use this file except in compliance with the License. * 18 | * You may obtain a copy of the License at * 19 | * * 20 | * http://www.apache.org/licenses/LICENSE-2.0 * 21 | * * 22 | * Unless required by applicable law or agreed to in writing, software * 23 | * distributed under the License is distributed on an "AS IS" BASIS, * 24 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or * 25 | * implied. * 26 | * See the License for the specific language governing permissions and * 27 | * limitations under the License. * 28 | ************************************************************************** 29 | * * 30 | * The most recent version of this package is available at github. * 31 | * * 32 | *************************************************************************/ 33 | #ifndef __INCLUDED_ram_1k_16_sp_H__ 34 | #define __INCLUDED_ram_1k_16_sp_H__ 35 | 36 | // SystemC memory model of ram_1k_16_sp 37 | // Generated by Catapult memory generator 38 | // Generated by: michaelf 39 | // Generated date: Wed Oct 2 11:14:08 2019 40 | 41 | // The following classes have been defined: 42 | // class ram_1k_16_sp a 0 delay "structural" model of the RAM 43 | 44 | // class ram_1k_16_sp_model::mem 45 | // A memory model that can be instanced and used for simulation and synthesis 46 | 47 | // class ram_1k_16_sp_model::port_0_port 48 | // a model of an external port with read/write capability 49 | 50 | #include 51 | #ifndef NO_ASSERTS 52 | #include 53 | #endif 54 | 55 | #pragma map_to_operator ram_1k_16_sp 56 | template < 57 | int ram_id, 58 | int data_width, 59 | int addr_width, 60 | int depth> 61 | class ram_1k_16_sp : public sc_module 62 | { 63 | public: 64 | sc_in< sc_lv > addr; 65 | sc_in< sc_lv > d; 66 | sc_in< bool > chip_en; 67 | sc_in< bool > wr_en; 68 | sc_in< bool > rd_en; 69 | sc_in< bool > clk; 70 | sc_out< sc_lv > q; 71 | 72 | #if !defined(__SYNTHESIS__) 73 | sc_signal > mem[depth]; 74 | #endif 75 | 76 | SC_CTOR(ram_1k_16_sp) : 77 | addr("addr") 78 | ,d("d") 79 | ,chip_en("chip_en") 80 | ,wr_en("wr_en") 81 | ,rd_en("rd_en") 82 | ,clk("clk") 83 | ,q("q") 84 | { 85 | SC_METHOD(seq_proc_1); 86 | dont_initialize(); 87 | sensitive << clk.pos(); 88 | } 89 | 90 | void seq_proc_1() { 91 | #if !defined(__SYNTHESIS__) 92 | if ( chip_en.read() ) { 93 | int address; 94 | // write X 95 | if ((chip_en==1) && (wr_en==1)) { 96 | vector_to_type( addr.read(), false, &address ); 97 | #if !defined(NO_ASSERTS) && !defined(__SYNTHESIS__) 98 | assert( address>=0 && address =0 && address () ); 112 | 113 | // write 114 | if ((chip_en==1) && (wr_en==1)) { 115 | vector_to_type( addr.read(), false, &address ); 116 | #if !defined(NO_ASSERTS) && !defined(__SYNTHESIS__) 117 | assert( address>=0 && address tb_read( int address ) const { 129 | #ifndef NO_ASSERTS 130 | assert( address>=0 && address < depth); 131 | #endif 132 | return mem[address]; 133 | } 134 | 135 | // NOTE: this method is intended for use by testbenches only. It is not synthesizable! 136 | void tb_write( int address, sc_lv data ) { 137 | #ifndef NO_ASSERTS 138 | assert( address>=0 && address < depth); 139 | #endif 140 | mem[address] = data; 141 | } 142 | 143 | #endif 144 | }; 145 | 146 | template 147 | class ram_1k_16_sp_model { 148 | public: 149 | #if defined(__SYNTHESIS__) 150 | template class mem{}; 151 | private: 152 | template class port_0_local; 153 | public: 154 | template class port_0_port; 155 | 156 | #elif defined (CCS_DUT_CYCLE) || defined (CCS_DUT_RTL) 157 | template 158 | class mem{}; 159 | private: 160 | template 161 | class port_0_local; 162 | public: 163 | template 164 | class port_0_port; 165 | 166 | #else 167 | template class mem{}; 169 | private: 170 | template class port_0_local; 172 | public: 173 | template class port_0_port; 175 | 176 | #endif 177 | 178 | // *********************************************** 179 | // TLM TLM TLM TLM TLM TLM TLM TLM TLM TLM TLM TLM 180 | // This code is only for TLM simulation only 181 | // *********************************************** 182 | 183 | template 184 | class mem 185 | { 186 | enum { 187 | addr_width = nbits::val, 188 | signedtype = mc_typedef_T_traits::issigned, 189 | data_width = mc_typedef_T_traits::bitwidth 190 | }; 191 | public: 192 | T readwrite (bool en_write, ac_int addr, T data=0) { 193 | port_0_port_instance.reset_chk.test(); 194 | #ifndef NO_ASSERTS 195 | assert( addr>=0 && addr addr, T data=0) { 205 | port_0_port_instance.reset_chk.test(); 206 | #ifndef NO_ASSERTS 207 | assert( addr>=0 && addr addr ) { 213 | #ifndef NO_ASSERTS 214 | assert( addr>=0 && addr=0 && index=0 && index=0 && address =0 && address &chip_en_arg) {} 259 | void chip_en(sc_signal &chip_en_arg) {} 260 | 261 | void clk(sc_in &clk_arg) { 262 | port_0_port_instance.clock_ok(); 263 | } 264 | void clk(sc_signal &clk_arg) { 265 | port_0_port_instance.clock_ok(); 266 | } 267 | 268 | port_0_local port_0_port_instance; 269 | private: 270 | T array[size]; 271 | friend class port_0_local; 272 | }; 273 | 274 | private: 275 | template 276 | class port_0_local 277 | { 278 | enum { 279 | addr_width = nbits::val, 280 | signedtype = mc_typedef_T_traits::issigned, 281 | data_width = mc_typedef_T_traits::bitwidth 282 | }; 283 | p2p_checker reset_chk; 284 | p2p_checker clock_chk; 285 | void clock_ok() {clock_chk.ok();} 286 | 287 | public: 288 | port_0_local (mem &my_parent, const char *name) 289 | : reset_chk( name, "call reset()", "access this memory") 290 | , clock_chk( name, "bind the clock port", "access this memory") 291 | , parent(my_parent) 292 | {} 293 | 294 | void reset() {reset_chk.ok();} 295 | 296 | T &operator [] (int index) { 297 | reset_chk.test(); 298 | clock_chk.test(); 299 | return parent.array[index]; 300 | } 301 | 302 | const T &operator [] (int index) const { 303 | reset_chk.test(); 304 | clock_chk.test(); 305 | #ifndef NO_ASSERTS 306 | assert( index>=0 && index addr, T data=0) { 312 | reset_chk.test(); 313 | clock_chk.test(); 314 | #ifndef NO_ASSERTS 315 | assert( addr>=0 && addr addr, T data=0) { 325 | reset_chk.test(); 326 | clock_chk.test(); 327 | #ifndef NO_ASSERTS 328 | assert( addr>=0 && addr addr ) { 334 | reset_chk.test(); 335 | clock_chk.test(); 336 | #ifndef NO_ASSERTS 337 | assert( addr>=0 && addr &parent; 344 | friend class mem; 345 | }; 346 | 347 | public: 348 | template 349 | class port_0_port 350 | { 351 | enum { 352 | addr_width = nbits::val, 353 | signedtype = mc_typedef_T_traits::issigned, 354 | data_width = mc_typedef_T_traits::bitwidth 355 | }; 356 | p2p_checker reset_chk; 357 | 358 | public: 359 | port_0_port(const char *name) 360 | : reset_chk(name, "call reset()", "access this port") 361 | , chan_ptr(0) 362 | , port_ptr(0) 363 | {} 364 | 365 | T readwrite(bool write, unsigned int addr, T data ) { 366 | reset_chk.test(); 367 | if ( bound_to_port ) 368 | return port_ptr->readwrite(write,addr,data); 369 | else 370 | return chan_ptr->readwrite(write,addr,data); 371 | } 372 | 373 | void write(unsigned int addr, T data ) { 374 | reset_chk.test(); 375 | if ( bound_to_port ) 376 | port_ptr->write(addr,data); 377 | else 378 | chan_ptr->write(addr,data); 379 | } 380 | 381 | T read(unsigned int addr) { 382 | reset_chk.test(); 383 | if ( bound_to_port ) 384 | return port_ptr->read(addr); 385 | else 386 | return chan_ptr->read(addr); 387 | } 388 | 389 | T &operator [] (int index) { 390 | reset_chk.test(); 391 | return (bound_to_port? (*port_ptr)[index] : (*chan_ptr)[index]); 392 | } 393 | 394 | void reset() {reset_chk.ok();} 395 | 396 | void operator() (port_0_local &c) { 397 | chan_ptr = &c; 398 | c.reset(); // Supress reset error on bound memory 399 | bound_to_port = false; 400 | } 401 | 402 | void operator() (port_0_port &c) { 403 | port_ptr = &c; 404 | c.reset(); // Supress reset error on bound port 405 | bound_to_port = true; 406 | } 407 | 408 | void operator() (mem &m) { 409 | chan_ptr = &m.port_0_port_instance; 410 | chan_ptr->reset(); // Supress reset error on bound memory 411 | bound_to_port = false; 412 | } 413 | 414 | private: 415 | bool bound_to_port; 416 | port_0_local *chan_ptr; 417 | port_0_port *port_ptr; 418 | }; 419 | 420 | // *********************************************** 421 | // SYN SYN SYN SYN SYN SYN SYN SYN SYN SYN SYN SYN 422 | // Synthesis code 423 | // *********************************************** 424 | 425 | private: 426 | template 427 | class port_0_local 428 | { 429 | enum { 430 | addr_width = nbits::val, 431 | signedtype = mc_typedef_T_traits::issigned, 432 | data_width = mc_typedef_T_traits::bitwidth 433 | }; 434 | p2p_checker reset_chk; 435 | p2p_checker clock_chk; 436 | class mem_ref 437 | { 438 | public: 439 | mem_ref( port_0_local &my_parent, ac_int addr) 440 | : address(addr), parent(my_parent) {} 441 | 442 | operator T() const { return parent.read(address); } 443 | 444 | inline mem_ref operator = ( T val ) { 445 | parent.write(address,val); 446 | return *this; 447 | } 448 | 449 | inline mem_ref operator = ( const mem_ref &val ) { return operator = ((T)val); } 450 | 451 | private: 452 | ac_int address; 453 | port_0_local &parent; 454 | }; 455 | 456 | void clock_ok() {clock_chk.ok();} 457 | 458 | public: 459 | port_0_local( const char *name) 460 | : reset_chk( name, "call reset()", "access this memory") 461 | , clock_chk( name, "bind the clock port", "access this memory") 462 | , addr(ccs_concat(name,"addr")) 463 | , d(ccs_concat(name,"d")) 464 | , wr_en(ccs_concat(name,"wr_en")) 465 | , rd_en(ccs_concat(name,"rd_en")) 466 | , q(ccs_concat(name,"q")) 467 | {} 468 | 469 | #pragma remove_out_reg 470 | #pragma design modulario 471 | T readwrite (bool en_write, ac_int addr, T data=0) { 472 | reset_chk.test(); 473 | clock_chk.test(); 474 | sc_lv temp_data; 475 | type_to_vector(data, (signedtype?true:false), temp_data); 476 | sc_lv temp_addr; 477 | type_to_vector(addr, (signedtype?true:false), temp_addr); 478 | if (en_write) { 479 | wr_en.write(1); 480 | } else { 481 | wr_en.write(0); 482 | } 483 | rd_en.write(1); 484 | addr.write( temp_addr ); 485 | d.write( temp_data ); 486 | #pragma unroll 487 | for (int lcnt=0; lcnt<1; lcnt++) wait(); 488 | #if defined(CALYPTO_SC) 489 | wait(); // Account for unreg outputs for SLEC 490 | #elif !defined(__SYNTHESIS__) 491 | wait(0.3, SC_NS); // Account for unreg outputs in simulation 492 | #endif 493 | wr_en.write(0); 494 | rd_en.write(0); 495 | #if !defined(CALYPTO_SC) 496 | // Return outputs to don't care to save area 497 | sc_lv dc; 498 | d.write( dc ); 499 | addr.write( dc ); 500 | #endif 501 | T return_data; 502 | vector_to_type(q.read(), (signedtype?true:false), &return_data); 503 | return return_data; 504 | } 505 | 506 | void write ( ac_int addr, T data ) { 507 | readwrite(true,addr,data); 508 | } 509 | 510 | T read ( ac_int addr ) { 511 | return readwrite(false,addr); 512 | } 513 | 514 | mem_ref operator [] (int index) { 515 | mem_ref write_ref(*this, index); 516 | return write_ref; 517 | } 518 | 519 | void reset() { 520 | wr_en.write(0); 521 | rd_en.write(0); 522 | addr.write(sc_dt::Log_0); 523 | d.write(sc_dt::Log_0); 524 | reset_chk.ok(); 525 | } 526 | 527 | sc_signal< sc_lv > addr; 528 | sc_signal< sc_lv > d; 529 | sc_signal< bool > wr_en; 530 | sc_signal< bool > rd_en; 531 | sc_signal< sc_lv > q; 532 | private: 533 | friend class mem; 534 | }; 535 | 536 | public: 537 | template 538 | class mem 539 | { 540 | enum { 541 | addr_width = nbits::val, 542 | signedtype = mc_typedef_T_traits::issigned, 543 | data_width = mc_typedef_T_traits::bitwidth 544 | }; 545 | class mem_ref 546 | { 547 | public: 548 | mem_ref( mem &my_parent, ac_int addr) 549 | : address(addr), parent(my_parent) {} 550 | 551 | operator T() const { return parent.read(address); } 552 | 553 | inline mem_ref operator = ( T val ) { 554 | parent.write(address,val); 555 | return *this; 556 | } 557 | 558 | inline mem_ref operator = ( const mem_ref &val ) { return operator = ((T)val); } 559 | 560 | private: 561 | ac_int address; 562 | mem &parent; 563 | }; 564 | 565 | public: 566 | mem ( const char *name) 567 | : RAM(ccs_concat(name, "RAM")) 568 | , port_0_port_instance(ccs_concat(name,"port_0")) 569 | { 570 | RAM.addr(port_0_port_instance.addr); 571 | RAM.d(port_0_port_instance.d); 572 | RAM.wr_en(port_0_port_instance.wr_en); 573 | RAM.rd_en(port_0_port_instance.rd_en); 574 | RAM.q(port_0_port_instance.q); 575 | } 576 | 577 | port_0_local port_0_port_instance; 578 | 579 | void chip_en(sc_in &chip_en_arg) { 580 | RAM.chip_en(chip_en_arg); 581 | } 582 | void chip_en(sc_signal &chip_en_arg) { 583 | RAM.chip_en(chip_en_arg); 584 | } 585 | 586 | void clk(sc_in &clk_arg) { 587 | RAM.clk(clk_arg); 588 | port_0_port_instance.clock_ok(); 589 | } 590 | void clk(sc_signal &clk_arg) { 591 | RAM.clk(clk_arg); 592 | port_0_port_instance.clock_ok(); 593 | } 594 | 595 | 596 | T read ( ac_int addr ) { 597 | return port_0_port_instance.read( addr ); 598 | } 599 | 600 | void write (ac_int addr, T data=0) { 601 | port_0_port_instance.write( addr, data ); 602 | } 603 | 604 | T readwrite (bool en_write, ac_int addr, T data=0) { 605 | return port_0_port_instance.readwrite( en_write, addr, data ); 606 | } 607 | 608 | mem_ref operator [] (int index) { 609 | mem_ref write_ref(*this, index); 610 | return write_ref; 611 | } 612 | 613 | void reset() { 614 | port_0_port_instance.reset(); 615 | } 616 | 617 | // NOTE: this method is intended for use by testbenches only. It is not synthesizable! 618 | T tb_read(int address) const { 619 | #ifndef NO_ASSERTS 620 | assert( address>=0 && address=0 && address temp_data; 633 | type_to_vector(val, (signedtype?true:false), temp_data); 634 | RAM.tb_write(address, temp_data); 635 | } 636 | 637 | private: 638 | ram_1k_16_sp<0, data_width, addr_width, size> RAM; 639 | }; 640 | 641 | template 642 | class port_0_port 643 | { 644 | enum { 645 | addr_width = nbits::val, 646 | signedtype = mc_typedef_T_traits::issigned, 647 | data_width = mc_typedef_T_traits::bitwidth 648 | }; 649 | p2p_checker reset_chk; 650 | 651 | class mem_ref 652 | { 653 | public: 654 | mem_ref( port_0_port &my_parent, ac_int addr) 655 | : address(addr), parent(my_parent) {} 656 | 657 | operator T() const { return parent.read(address); } 658 | 659 | inline mem_ref operator = ( T val ) { 660 | parent.write(address,val); 661 | return *this; 662 | } 663 | 664 | inline mem_ref operator = ( const mem_ref &val ) { return operator = ((T)val); } 665 | 666 | private: 667 | ac_int address; 668 | port_0_port &parent; 669 | }; 670 | 671 | public: 672 | port_0_port( const char *name) 673 | : reset_chk( name, "call reset()", "access this memory") 674 | , addr(ccs_concat(name,"addr")) 675 | , d(ccs_concat(name,"d")) 676 | , wr_en(ccs_concat(name,"wr_en")) 677 | , rd_en(ccs_concat(name,"rd_en")) 678 | , q(ccs_concat(name,"q")) 679 | {} 680 | 681 | #pragma remove_out_reg 682 | #pragma design modulario 683 | T readwrite (bool en_write, ac_int addr, T data=0) { 684 | reset_chk.test(); 685 | sc_lv temp_data; 686 | type_to_vector(data, (signedtype?true:false), temp_data); 687 | sc_lv temp_addr; 688 | type_to_vector(addr, (signedtype?true:false), temp_addr); 689 | if (en_write) { 690 | wr_en.write(1); 691 | } else { 692 | wr_en.write(0); 693 | } 694 | rd_en.write(1); 695 | addr.write( temp_addr ); 696 | d.write( temp_data ); 697 | #pragma unroll 698 | for (int lcnt=0; lcnt<1; lcnt++) wait(); 699 | #if defined(CALYPTO_SC) 700 | wait(); // Account for unreg outputs for SLEC 701 | #elif !defined(__SYNTHESIS__) 702 | wait(0.3, SC_NS); // Account for unreg outputs in simulation 703 | #endif 704 | wr_en.write(0); 705 | rd_en.write(0); 706 | #if !defined(CALYPTO_SC) 707 | // Return outputs to don't care to save area 708 | sc_lv dc; 709 | d.write( dc ); 710 | addr.write( dc ); 711 | #endif 712 | T return_data; 713 | vector_to_type(q.read(), (signedtype?true:false), &return_data); 714 | return return_data; 715 | } 716 | 717 | void write ( ac_int addr, T data ) { 718 | readwrite(true,addr,data); 719 | } 720 | 721 | T read ( ac_int addr ) { 722 | return readwrite(false,addr); 723 | } 724 | 725 | void reset() { 726 | wr_en.write(0); 727 | rd_en.write(0); 728 | addr.write(sc_dt::Log_0); 729 | d.write(sc_dt::Log_0); 730 | reset_chk.ok(); 731 | } 732 | 733 | sc_out< sc_lv > addr; 734 | sc_out< sc_lv > d; 735 | sc_out< bool > wr_en; 736 | sc_out< bool > rd_en; 737 | sc_in< sc_lv > q; 738 | 739 | mem_ref operator [] (int index) { 740 | mem_ref write_ref(*this, index); 741 | return write_ref; 742 | } 743 | 744 | template void bind( C &c ) { 745 | addr(c.addr); 746 | d(c.d); 747 | wr_en(c.wr_en); 748 | rd_en(c.rd_en); 749 | q(c.q); 750 | } 751 | 752 | template void operator() (C& c) { 753 | bind(c); 754 | } 755 | 756 | void operator() (mem &m) { 757 | addr(m.port_0_port_instance.addr); 758 | d(m.port_0_port_instance.d); 759 | wr_en(m.port_0_port_instance.wr_en); 760 | rd_en(m.port_0_port_instance.rd_en); 761 | q(m.port_0_port_instance.q); 762 | } 763 | 764 | }; 765 | 766 | }; 767 | #endif // ifndef __INCLUDED_ram_1k_16_sp_H__ 768 | 769 | 770 | -------------------------------------------------------------------------------- /WalkThroughs/EdgeDetect/src/ram_1k_16_sp.tcl: -------------------------------------------------------------------------------- 1 | flow package require MemGen 2 | flow run /MemGen/MemoryGenerator_BuildLib { 3 | VENDOR * 4 | RTLTOOL OasysRTL 5 | TECHNOLOGY * 6 | LIBRARY nangate-45nm_mem 7 | MODULE ram_1k_16_sp 8 | OUTPUT_DIR ./ 9 | FILES { 10 | { FILENAME ./ram_1k_16_sp.v FILETYPE Verilog PATHTYPE relative MODELTYPE GENERIC PARSE 1 STATICFILE 1 VHDL_LIB_MAPS work } 11 | { FILENAME ./ram_1k_16_sp.vhd FILETYPE VHDL PATHTYPE relative MODELTYPE GENERIC } 12 | { FILENAME ./ram_1k_16_sp_liberty.lib FILETYPE Liberty PATHTYPE relative MODELTYPE synthesis PARSE 1 STATICFILE 1 VHDL_LIB_MAPS work } 13 | } 14 | LIBS_LEF ram_1k_16_sp.lef 15 | VHDLARRAYPATH mem 16 | WRITEDELAY 0.1 17 | INITDELAY 1 18 | READDELAY 0.4 19 | VERILOGARRAYPATH mem 20 | INPUTDELAY 0.01 21 | WIDTH data_width 22 | AREA 99353 23 | RDWRRESOLUTION UNKNOWN 24 | WRITELATENCY 1 25 | LIBS_LIBERTY ram_1k_16_sp_liberty.lib 26 | VHDL_LIB_MAPS {work ./work nangate45_mem_lib ./work} 27 | READLATENCY 1 28 | DEPTH depth 29 | PARAMETERS { 30 | { PARAMETER data_width TYPE hdl IGNORE 0 MIN 16 MAX 16 DEFAULT 16 } 31 | { PARAMETER addr_width TYPE hdl IGNORE 0 MIN 10 MAX 10 DEFAULT 10 } 32 | { PARAMETER depth TYPE hdl IGNORE 0 MIN {} MAX {} DEFAULT 0 } 33 | } 34 | PORTS { 35 | { NAME port_0 MODE ReadWrite } 36 | } 37 | PINMAPS { 38 | { PHYPIN addr LOGPIN ADDRESS DIRECTION in WIDTH addr_width PHASE {} DEFAULT {} PORTS port_0 } 39 | { PHYPIN d LOGPIN DATA_IN DIRECTION in WIDTH data_width PHASE {} DEFAULT {} PORTS port_0 } 40 | { PHYPIN chip_en LOGPIN ENABLE DIRECTION in WIDTH 1.0 PHASE 1 DEFAULT {} PORTS port_0 } 41 | { PHYPIN wr_en LOGPIN WRITE_ENABLE DIRECTION in WIDTH 1.0 PHASE 1 DEFAULT {} PORTS port_0 } 42 | { PHYPIN rd_en LOGPIN READ_ENABLE DIRECTION in WIDTH 1.0 PHASE 1 DEFAULT {} PORTS port_0 } 43 | { PHYPIN clk LOGPIN CLOCK DIRECTION in WIDTH 1.0 PHASE 1 DEFAULT {} PORTS port_0 } 44 | { PHYPIN q LOGPIN DATA_OUT DIRECTION out WIDTH data_width PHASE {} DEFAULT {} PORTS port_0 } 45 | } 46 | 47 | } 48 | -------------------------------------------------------------------------------- /WalkThroughs/EdgeDetect/src/ram_1k_16_sp.v: -------------------------------------------------------------------------------- 1 | module ram_1k_16_sp #( 2 | parameter data_width = 16, 3 | parameter addr_width = 10, 4 | parameter depth = 1024 5 | )( 6 | addr, d, chip_en, wr_en, rd_en, clk, q 7 | ); 8 | 9 | input [addr_width-1:0] addr; 10 | input [data_width-1:0] d; 11 | input chip_en; 12 | input wr_en; 13 | input rd_en; 14 | input clk; 15 | output[data_width-1:0] q; 16 | 17 | // synopsys translate_off 18 | reg [data_width-1:0] q; 19 | reg [data_width-1:0] mem [depth-1:0]; 20 | 21 | always @(posedge clk) begin 22 | if (chip_en) begin 23 | q <= mem[addr]; 24 | if (wr_en) begin 25 | mem[addr] <= d; 26 | end 27 | end 28 | end 29 | 30 | // synopsys translate_on 31 | 32 | endmodule 33 | -------------------------------------------------------------------------------- /WalkThroughs/EdgeDetect/src/ram_1k_16_sp.vhd: -------------------------------------------------------------------------------- 1 | -- Block Single Port RAM Read Before Write 2 | 3 | LIBRARY IEEE; 4 | USE IEEE.STD_LOGIC_1164.ALL; 5 | USE IEEE.Numeric_Std.ALL; 6 | 7 | PACKAGE ram_1k_16_sp_pkg IS 8 | COMPONENT ram_1k_16_sp 9 | GENERIC ( 10 | data_width : integer := 16; 11 | addr_width : integer := 10; 12 | depth : integer := 1024 13 | ); 14 | PORT ( 15 | clk : IN std_logic; 16 | addr : IN std_logic_vector(addr_width-1 DOWNTO 0); 17 | wr_en : IN std_logic; 18 | rd_en : IN std_logic; 19 | chip_en : IN std_logic; 20 | d : IN std_logic_vector(data_width-1 DOWNTO 0); 21 | q : OUT std_logic_vector(data_width-1 DOWNTO 0) 22 | ); 23 | END COMPONENT; 24 | END ram_1k_16_sp_pkg; 25 | 26 | LIBRARY IEEE; 27 | USE IEEE.STD_LOGIC_1164.ALL; 28 | USE IEEE.Numeric_Std.ALL; 29 | --LIBRARY nangate-45nm_mem; 30 | USE work.ram_1k_16_sp_pkg.ALL; 31 | 32 | ENTITY ram_1k_16_sp IS 33 | GENERIC ( 34 | data_width : integer := 16; 35 | addr_width : integer := 10; 36 | depth : integer := 1024 37 | ); 38 | PORT ( 39 | clk : IN std_logic; 40 | addr : IN std_logic_vector(addr_width-1 DOWNTO 0); 41 | wr_en : IN std_logic; 42 | rd_en : IN std_logic; 43 | chip_en : IN std_logic; 44 | d : IN std_logic_vector(data_width-1 DOWNTO 0); 45 | q : OUT std_logic_vector(data_width-1 DOWNTO 0) 46 | ); 47 | 48 | END ram_1k_16_sp; 49 | 50 | ARCHITECTURE rtl OF ram_1k_16_sp IS 51 | 52 | TYPE ram_t IS ARRAY (depth-1 DOWNTO 0) OF std_logic_vector(data_width-1 DOWNTO 0); 53 | SIGNAL mem : ram_t := (OTHERS => (OTHERS => '0')); 54 | 55 | BEGIN 56 | PROCESS (clk) 57 | BEGIN 58 | --synopsys translate_off 59 | IF (rising_edge(clk)) THEN 60 | IF (chip_en ='1') THEN 61 | IF (rd_en='1') THEN 62 | q <= mem(to_integer(unsigned(addr))) ; -- read port 63 | END IF; 64 | IF (wr_en='1') THEN 65 | mem(to_integer(unsigned(addr))) <= d; 66 | END IF; 67 | END IF; 68 | END IF; 69 | --synopsys translate_on 70 | END PROCESS; 71 | END rtl; 72 | 73 | 74 | -------------------------------------------------------------------------------- /WalkThroughs/EdgeDetect/src/ram_1k_16_sp_trans_rsc.h: -------------------------------------------------------------------------------- 1 | /************************************************************************** 2 | * * 3 | * Edge Detect Design Walkthrough for HLS * 4 | * * 5 | * Software Version: 1.0 * 6 | * * 7 | * Release Date : Tue Jan 14 15:40:43 PST 2020 * 8 | * Release Type : Production Release * 9 | * Release Build : 1.0.0 * 10 | * * 11 | * Copyright 2020, Mentor Graphics Corporation, * 12 | * * 13 | * All Rights Reserved. * 14 | * 15 | ************************************************************************** 16 | * Licensed under the Apache License, Version 2.0 (the "License"); * 17 | * you may not use this file except in compliance with the License. * 18 | * You may obtain a copy of the License at * 19 | * * 20 | * http://www.apache.org/licenses/LICENSE-2.0 * 21 | * * 22 | * Unless required by applicable law or agreed to in writing, software * 23 | * distributed under the License is distributed on an "AS IS" BASIS, * 24 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or * 25 | * implied. * 26 | * See the License for the specific language governing permissions and * 27 | * limitations under the License. * 28 | ************************************************************************** 29 | * * 30 | * The most recent version of this package is available at github. * 31 | * * 32 | *************************************************************************/ 33 | #ifndef __INCLUDED_ram_1k_16_sp_trans_rsc_H__ 34 | #define __INCLUDED_ram_1k_16_sp_trans_rsc_H__ 35 | #include 36 | 37 | template < 38 | int data_width 39 | ,int addr_width 40 | ,int depth 41 | > 42 | class ram_1k_16_sp_trans_rsc : public mc_wire_trans_rsc_base 43 | { 44 | public: 45 | sc_in< sc_lv > addr; 46 | sc_in< sc_lv > d; 47 | sc_in< sc_logic > chip_en; 48 | sc_in< sc_logic > wr_en; 49 | sc_in< sc_logic > rd_en; 50 | sc_in< bool > clk; 51 | sc_out< sc_lv > q; 52 | 53 | typedef mc_wire_trans_rsc_base base; 54 | MC_EXPOSE_NAMES_OF_BASE(base); 55 | 56 | SC_HAS_PROCESS( ram_1k_16_sp_trans_rsc ); 57 | ram_1k_16_sp_trans_rsc(const sc_module_name& name, bool phase, double clk_skew_delay=0.0) 58 | : base(name, phase, clk_skew_delay) 59 | ,addr("addr") 60 | ,d("d") 61 | ,chip_en("chip_en") 62 | ,wr_en("wr_en") 63 | ,rd_en("rd_en") 64 | ,clk("clk") 65 | ,q("q") 66 | ,_is_connected_port_0(true) 67 | ,_is_connected_port_0_messaged(false) 68 | { 69 | SC_METHOD(at_active_clock_edge); 70 | sensitive << (phase ? clk.pos() : clk.neg()); 71 | this->dont_initialize(); 72 | 73 | MC_METHOD(clk_skew_delay); 74 | this->sensitive << this->_clk_skew_event; 75 | this->dont_initialize(); 76 | } 77 | 78 | virtual void start_of_simulation() { 79 | if ((base::_holdtime == 0.0) && this->get_attribute("CLK_SKEW_DELAY")) { 80 | base::_holdtime = ((sc_attribute*)(this->get_attribute("CLK_SKEW_DELAY")))->value; 81 | } 82 | if (base::_holdtime > 0) { 83 | std::ostringstream msg; 84 | msg << "ram_1k_16_sp_trans_rsc CLASS_STARTUP - CLK_SKEW_DELAY = " 85 | << base::_holdtime << " ps @ " << sc_time_stamp(); 86 | SC_REPORT_INFO(this->name(), msg.str().c_str()); 87 | } 88 | reset_memory(); 89 | } 90 | 91 | virtual void inject_value(int addr, int idx_lhs, int mywidth, sc_lv_base& rhs, int idx_rhs) { 92 | this->set_value(addr, idx_lhs, mywidth, rhs, idx_rhs); 93 | } 94 | 95 | virtual void extract_value(int addr, int idx_rhs, int mywidth, sc_lv_base& lhs, int idx_lhs) { 96 | this->get_value(addr, idx_rhs, mywidth, lhs, idx_lhs); 97 | } 98 | 99 | private: 100 | void at_active_clock_edge() { 101 | base::at_active_clk(); 102 | } 103 | 104 | void clk_skew_delay() { 105 | this->exchange_value(0); 106 | if ( chip_en.read() == 0 ) return; // everything stalls if enable is inactive 107 | 108 | if (addr.get_interface()) 109 | _addr = addr.read(); 110 | else { 111 | _is_connected_port_0 = false; 112 | } 113 | if (d.get_interface()) 114 | _d = d.read(); 115 | else { 116 | _is_connected_port_0 = false; 117 | } 118 | if (chip_en.get_interface()) 119 | _chip_en = chip_en.read(); 120 | if (wr_en.get_interface()) 121 | _wr_en = wr_en.read(); 122 | if (rd_en.get_interface()) 123 | _rd_en = rd_en.read(); 124 | 125 | // Write 126 | int _w_addr_port_0 = -1; 127 | if ( _is_connected_port_0 && (_wr_en==1)) { 128 | _w_addr_port_0 = get_addr(_addr, "addr"); 129 | if (_w_addr_port_0 >= 0) 130 | inject_value(_w_addr_port_0, 0, data_width, _d, 0); 131 | } 132 | if( !_is_connected_port_0 && !_is_connected_port_0_messaged) { 133 | std::ostringstream msg;msg << "port_0 is not fully connected and writes on it will be ignored"; 134 | SC_REPORT_WARNING(this->name(), msg.str().c_str()); 135 | _is_connected_port_0_messaged = true; 136 | } 137 | 138 | // Sync Read 139 | if ((_rd_en==1)) { 140 | const int addr = get_addr(_addr, "addr"); 141 | if (addr >= 0) 142 | { 143 | if (addr==_w_addr_port_0) { 144 | sc_lv dc; // X 145 | _q = dc; 146 | } 147 | else 148 | extract_value(addr, 0, data_width, _q, 0); 149 | } 150 | else { 151 | sc_lv dc; // X 152 | _q = dc; 153 | } 154 | } 155 | if (q.get_interface()) 156 | q = _q; 157 | this->_value_changed.notify(SC_ZERO_TIME); 158 | } 159 | 160 | int get_addr(const sc_lv& addr, const char* pin_name) { 161 | if (addr.is_01()) { 162 | const int cur_addr = addr.to_uint(); 163 | if (cur_addr < 0 || cur_addr >= depth) { 164 | #ifdef CCS_SYSC_DEBUG 165 | std::ostringstream msg; 166 | msg << "Invalid address '" << cur_addr << "' out of range [0:" << depth-1 << "]"; 167 | SC_REPORT_WARNING(pin_name, msg.str().c_str()); 168 | #endif 169 | return -1; 170 | } else { 171 | return cur_addr; 172 | } 173 | } else { 174 | #ifdef CCS_SYSC_DEBUG 175 | std::ostringstream msg; 176 | msg << "Invalid Address '" << addr << "' contains 'X' or 'Z'"; 177 | SC_REPORT_WARNING(pin_name, msg.str().c_str()); 178 | #endif 179 | return -1; 180 | } 181 | } 182 | 183 | void reset_memory() { 184 | this->zero_data(); 185 | _addr = sc_lv(); 186 | _d = sc_lv(); 187 | _chip_en = SC_LOGIC_X; 188 | _wr_en = SC_LOGIC_X; 189 | _rd_en = SC_LOGIC_X; 190 | _is_connected_port_0 = true; 191 | _is_connected_port_0_messaged = false; 192 | } 193 | 194 | sc_lv _addr; 195 | sc_lv _d; 196 | sc_logic _chip_en; 197 | sc_logic _wr_en; 198 | sc_logic _rd_en; 199 | sc_lv _q; 200 | bool _is_connected_port_0; 201 | bool _is_connected_port_0_messaged; 202 | }; 203 | #endif // ifndef __INCLUDED_ram_1k_16_sp_trans_rsc_H__ 204 | 205 | 206 | --------------------------------------------------------------------------------