├── 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