forked from altera-fpga/hls-samples
-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathmain.cpp
163 lines (133 loc) · 4.42 KB
/
main.cpp
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
#include <iostream>
// oneAPI headers
#include <sycl/ext/intel/fpga_extensions.hpp>
#include <sycl/sycl.hpp>
#include "exception_handler.hpp"
constexpr int kVectSize = 128;
// Forward declare the kernel names in the global scope.
// This FPGA best practice reduces name mangling in the optimization reports.
class IDNaive;
// Minimum capacity of a pipe.
// Set to 0 to allow the compiler to save area if possible.
constexpr size_t kPipeMinCapacity = 0;
// Pipes
class IDPipeIn0;
using PipeIn0 = sycl::ext::intel::experimental::pipe<
IDPipeIn0, // An identifier for the pipe
int, // The type of data in the pipe
kPipeMinCapacity // The capacity of the pipe
>;
class IDPipeIn1;
using PipeIn1 = sycl::ext::intel::experimental::pipe<
IDPipeIn1, // An identifier for the pipe
int, // The type of data in the pipe
kPipeMinCapacity // The capacity of the pipe
>;
class IDPipeOut;
using PipeOut = sycl::ext::intel::experimental::pipe<
IDPipeOut, // An identifier for the pipe
int, // The type of data in the pipe
kPipeMinCapacity // The capacity of the pipe
>;
///////////////////////////////////////
struct NaiveKernel {
int len;
void operator()() const {
int array_a_b[kVectSize];
int array_b_c[kVectSize];
int array_c_d[kVectSize];
int array_a_d[kVectSize];
// loopA
[[intel::initiation_interval(1)]]
for (size_t i = 0; i < len; i++) {
int in0 = PipeIn0::read();
int in1 = PipeIn1::read();
array_a_b[i] = in0;
array_a_d[i] = in1;
}
// loopB
[[intel::initiation_interval(1)]]
for (size_t i = 0; i < len; i++) {
int tmp = array_a_b[i];
tmp += i;
array_b_c[i] = tmp;
}
// loopC
[[intel::initiation_interval(1)]]
for (size_t i = 0; i < len; i++) {
int tmp = array_b_c[i];
tmp += i;
array_c_d[i] = tmp;
}
// loopD
[[intel::initiation_interval(1)]]
for (size_t i = 0; i < len; i++) {
int tmp0 = array_c_d[i];
int tmp1 = array_a_d[i];
int out = tmp0 + tmp1;
PipeOut::write(out);
}
}
};
int main() {
bool passed = false;
try {
// Use compile-time macros to select either:
// - the FPGA emulator device (CPU emulation of the FPGA)
// - the FPGA device (a real FPGA)
// - the simulator device
#if FPGA_SIMULATOR
auto selector = sycl::ext::intel::fpga_simulator_selector_v;
#elif FPGA_HARDWARE
auto selector = sycl::ext::intel::fpga_selector_v;
#else // #if FPGA_EMULATOR
auto selector = sycl::ext::intel::fpga_emulator_selector_v;
#endif
sycl::queue q(selector, fpga_tools::exception_handler,
sycl::property::queue::enable_profiling{});
auto device = q.get_device();
std::cout << "Running on device: "
<< device.get_info<sycl::info::device::name>().c_str()
<< std::endl;
int *a = new int[kVectSize];
int *b = new int[kVectSize];
// Generate input data
for (int i = 0; i < kVectSize; i++) {
a[i] = i;
b[i] = (kVectSize - i);
PipeIn0::write(q, i);
PipeIn1::write(q, kVectSize - i);
}
// Call the kernel
auto e = q.single_task<IDNaive>(NaiveKernel{kVectSize});
// verify that output is correct
passed = true;
for (int i = 0; i < kVectSize; i++) {
int expected = a[i] * 3 + b[i];
int result = PipeOut::read(q);
if (result != expected) {
std::cout << "idx=" << i << ": naive result " << result
<< ", expected (" << expected << ") ." << std::endl;
passed = false;
}
}
// Wait for kernel to exit
e.wait();
std::cout << (passed ? "PASSED" : "FAILED") << std::endl;
delete[] a;
delete[] b;
} catch (sycl::exception const &e) {
// Catches exceptions in the host code.
std::cerr << "Caught a SYCL host exception:\n" << e.what() << "\n";
// Most likely the runtime couldn't find FPGA hardware!
if (e.code().value() == CL_DEVICE_NOT_FOUND) {
std::cerr << "If you are targeting an FPGA, please ensure that your "
"system has a correctly configured FPGA board.\n";
std::cerr << "Run sys_check in the oneAPI root directory to verify.\n";
std::cerr << "If you are targeting the FPGA emulator, compile with "
"-DFPGA_EMULATOR.\n";
}
std::terminate();
}
return passed ? EXIT_SUCCESS : EXIT_FAILURE;
}