-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathvadd_comparison.cpp
More file actions
166 lines (137 loc) · 5.81 KB
/
Copy pathvadd_comparison.cpp
File metadata and controls
166 lines (137 loc) · 5.81 KB
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
164
165
166
#include <iostream>
#include <chrono>
#include <cstdlib>
// Dummy definitions for HLS headers to enable CPU compilation
#define ap_int int
#define hls_stream int
#pragma HLS INTERFACE
#pragma HLS PIPELINE
#pragma HLS ARRAY_PARTITION
// =============================================
// Original Simple Kernel (Non-burst version)
// =============================================
extern "C" {
void vadd_simple(const int *A, const int *B, int *C, int size) {
#pragma HLS INTERFACE m_axi port=A offset=slave bundle=gmem
#pragma HLS INTERFACE m_axi port=B offset=slave bundle=gmem
#pragma HLS INTERFACE m_axi port=C offset=slave bundle=gmem
#pragma HLS INTERFACE s_axilite port=A bundle=control
#pragma HLS INTERFACE s_axilite port=B bundle=control
#pragma HLS INTERFACE s_axilite port=C bundle=control
#pragma HLS INTERFACE s_axilite port=size bundle=control
#pragma HLS INTERFACE s_axilite port=return bundle=control
// Main loop
for (int i = 0; i < size; i++) {
#pragma HLS PIPELINE II=1
C[i] = A[i] + B[i];
}
}
}
// =============================================
// Optimized Burst Kernel
// =============================================
#define MAX_SIZE 1024
#define BURST_LEN 64
void vadd_burst(volatile int* A, volatile int* B, volatile int* C, int N) {
#pragma HLS INTERFACE m_axi port=A offset=slave bundle=gmem0 depth=1024
#pragma HLS INTERFACE m_axi port=B offset=slave bundle=gmem1 depth=1024
#pragma HLS INTERFACE m_axi port=C offset=slave bundle=gmem2 depth=1024
#pragma HLS INTERFACE s_axilite port=N
#pragma HLS INTERFACE s_axilite port=return
// Local buffers for burst transfers
int buffer_A[BURST_LEN];
int buffer_B[BURST_LEN];
int buffer_C[BURST_LEN];
#pragma HLS ARRAY_PARTITION variable=buffer_A complete
#pragma HLS ARRAY_PARTITION variable=buffer_B complete
#pragma HLS ARRAY_PARTITION variable=buffer_C complete
// Process data in bursts
burst_loop: for (int base = 0; base < N; base += BURST_LEN) {
int chunk_size = (base + BURST_LEN > N) ? N - base : BURST_LEN;
// Burst read from A and B
read_loop: for (int i = 0; i < chunk_size; i++) {
#pragma HLS PIPELINE II=1
buffer_A[i] = A[base + i];
buffer_B[i] = B[base + i];
}
// Compute vector addition
compute_loop: for (int i = 0; i < chunk_size; i++) {
#pragma HLS PIPELINE II=1
buffer_C[i] = buffer_A[i] + buffer_B[i];
}
// Burst write to C
write_loop: for (int i = 0; i < chunk_size; i++) {
#pragma HLS PIPELINE II=1
C[base + i] = buffer_C[i];
}
}
}
// =============================================
// Main test program with performance comparison
// =============================================
int main() {
const int TEST_SIZE = 1024;
// Allocate memory
int* A = new int[TEST_SIZE];
int* B = new int[TEST_SIZE];
int* C_simple = new int[TEST_SIZE];
int* C_burst = new int[TEST_SIZE];
// Initialize test data
for (int i = 0; i < TEST_SIZE; i++) {
A[i] = rand() % 1000;
B[i] = rand() % 1000;
}
std::cout << "==================================================" << std::endl;
std::cout << "Vector Addition Performance Comparison" << std::endl;
std::cout << "Test Size: " << TEST_SIZE << " elements" << std::endl;
std::cout << "Burst Length: " << BURST_LEN << std::endl;
std::cout << "==================================================" << std::endl;
// ---------------------------
// Run SIMPLE kernel
// ---------------------------
auto start_simple = std::chrono::high_resolution_clock::now();
vadd_simple(A, B, C_simple, TEST_SIZE);
auto end_simple = std::chrono::high_resolution_clock::now();
auto duration_simple = std::chrono::duration_cast<std::chrono::nanoseconds>(end_simple - start_simple);
// ---------------------------
// Run BURST kernel
// ---------------------------
auto start_burst = std::chrono::high_resolution_clock::now();
vadd_burst(A, B, C_burst, TEST_SIZE);
auto end_burst = std::chrono::high_resolution_clock::now();
auto duration_burst = std::chrono::duration_cast<std::chrono::nanoseconds>(end_burst - start_burst);
// ---------------------------
// Verify results match
// ---------------------------
bool match = true;
for (int i = 0; i < TEST_SIZE; i++) {
if (C_simple[i] != C_burst[i]) {
match = false;
std::cout << "Mismatch at index " << i << ": " << C_simple[i] << " vs " << C_burst[i] << std::endl;
break;
}
}
// ---------------------------
// Print performance results
// ---------------------------
std::cout << std::endl;
std::cout << "Results Verification: " << (match ? "✅ PASS (both kernels produce identical output)" : "❌ FAIL") << std::endl;
std::cout << std::endl;
std::cout << "1. Simple Kernel (Single element access):" << std::endl;
std::cout << " Execution Time: " << duration_simple.count() << " ns" << std::endl;
std::cout << " Throughput: " << (TEST_SIZE * 1000.0 / duration_simple.count()) << " Mops/s" << std::endl;
std::cout << std::endl;
std::cout << "2. Burst Optimized Kernel:" << std::endl;
std::cout << " Execution Time: " << duration_burst.count() << " ns" << std::endl;
std::cout << " Throughput: " << (TEST_SIZE * 1000.0 / duration_burst.count()) << " Mops/s" << std::endl;
std::cout << std::endl;
double speedup = (double)duration_simple.count() / duration_burst.count();
std::cout << "Performance Speedup: " << speedup << "x" << std::endl;
std::cout << "==================================================" << std::endl;
// Cleanup
delete[] A;
delete[] B;
delete[] C_simple;
delete[] C_burst;
return 0;
}