-
Notifications
You must be signed in to change notification settings - Fork 4
/
Aurora.hpp
353 lines (302 loc) · 10.1 KB
/
Aurora.hpp
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
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
/*
* Copyright 2023-2024 Gerrit Pape ([email protected])
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#pragma once
#include "experimental/xrt_kernel.h"
#include "experimental/xrt_ip.h"
#include <cmath>
#include <bitset>
double get_wtime()
{
struct timespec time;
clock_gettime(CLOCK_REALTIME, &time);
return time.tv_sec + (double)time.tv_nsec / 1e9;
}
// control s axi addresses
static const uint32_t CONFIGURATION_ADDRESS = 0x00000010;
static const uint32_t FIFO_THRESHOLDS_ADDRESS = 0x00000014;
static const uint32_t CORE_STATUS_ADDRESS = 0x00000018;
static const uint32_t STATUS_NOT_OK_COUNT_ADDRESS = 0x0000001c;
static const uint32_t FIFO_STATUS_ADDRESS = 0x00000020;
static const uint32_t FIFO_RX_OVERFLOW_COUNT_ADDRESS = 0x00000024;
static const uint32_t FIFO_TX_OVERFLOW_COUNT_ADDRESS = 0x00000028;
static const uint32_t NFC_FULL_TRIGGER_COUNT_ADDRESS = 0x0000002c;
static const uint32_t NFC_EMPTY_TRIGGER_COUNT_ADDRESS = 0x00000030;
static const uint32_t SW_RESET_ADDRESS = 0x00000034;
static const uint32_t FRAMES_RECEIVED_ADDRESS = 0x00000038;
static const uint32_t FRAMES_WITH_ERRORS_ADDRESS = 0x0000003c;
// masks for core status bits
static const uint32_t GT_POWERGOOD = 0x0000000f;
static const uint32_t LINE_UP = 0x000000f0;
static const uint32_t GT_PLL_LOCK = 0x00000100;
static const uint32_t MMCM_NOT_LOCKED_OUT = 0x00000200;
static const uint32_t HARD_ERR = 0x00000400;
static const uint32_t SOFT_ERR = 0x00000800;
static const uint32_t CHANNEL_UP = 0x00001000;
static const uint32_t CORE_STATUS_OK = GT_POWERGOOD | LINE_UP | GT_PLL_LOCK | CHANNEL_UP;
// masks for fifo status bits
static const uint32_t FIFO_TX_PROG_EMPTY = 0x00000001;
static const uint32_t FIFO_TX_ALMOST_EMPTY = 0x00000002;
static const uint32_t FIFO_TX_PROG_FULL = 0x00000004;
static const uint32_t FIFO_TX_ALMOST_FULL = 0x00000008;
static const uint32_t FIFO_RX_PROG_EMPTY = 0x00000010;
static const uint32_t FIFO_RX_ALMOST_EMPTY = 0x00000020;
static const uint32_t FIFO_RX_PROG_FULL = 0x00000040;
static const uint32_t FIFO_RX_ALMOST_FULL = 0x00000080;
static const char *fifo_status_name[8] = {
"FIFO tx prog empty",
"FIFO tx almost empty",
"FIFO tx prog full",
"FIFO tx almost full",
"FIFO rx prog empty",
"FIFO rx almost empty",
"FIFO rx prog full",
"FIFO rx almost full",
};
// masks for configuration bits
static const uint32_t HAS_TKEEP = 0x000001;
static const uint32_t HAS_TLAST = 0x000002;
static const uint32_t FIFO_WIDTH = 0x0007fc;
static const uint32_t FIFO_DEPTH = 0x007800;
static const uint32_t RX_EQ_MODE_BINARY = 0x018000;
static const uint32_t INS_LOSS_NYQ = 0x3e0000;
static const char *rx_eq_mode_names[4] = {
"AUTO",
"LPM",
"DFE",
""
};
class Aurora
{
public:
Aurora(xrt::ip ip) : ip(ip)
{
// read constant configuration information
uint32_t configuration = ip.read_register(CONFIGURATION_ADDRESS);
has_tkeep = (configuration & HAS_TKEEP);
has_tlast = (configuration & HAS_TLAST) >> 1;
fifo_width = (configuration & FIFO_WIDTH) >> 2;
fifo_depth = pow(2, (configuration & FIFO_DEPTH) >> 11);
rx_eq_mode = (configuration & RX_EQ_MODE_BINARY) >> 15;
ins_loss_nyq = (configuration & INS_LOSS_NYQ) >> 17;
uint32_t fifo_thresholds = ip.read_register(FIFO_THRESHOLDS_ADDRESS);
fifo_prog_full_threshold = (fifo_thresholds & 0xffff0000) >> 16;
fifo_prog_empty_threshold = (fifo_thresholds & 0x0000ffff);
}
Aurora(std::string name, xrt::device &device, xrt::uuid &xclbin_uuid)
: Aurora(xrt::ip(device, xclbin_uuid, name)) {}
std::string create_name_from_instance(uint32_t instance)
{
char name[100];
snprintf(name, 100, "aurora_hls_%u:{aurora_hls_%u}", instance, instance);
return std::string(name);
}
Aurora(uint32_t instance, xrt::device &device, xrt::uuid &xclbin_uuid)
: Aurora(create_name_from_instance(instance), device, xclbin_uuid) {}
Aurora() {}
bool has_framing()
{
return has_tlast;
}
const char *get_rx_eq_mode_name()
{
return rx_eq_mode_names[rx_eq_mode];
}
uint32_t get_configuration()
{
return ip.read_register(CONFIGURATION_ADDRESS);
}
void print_configuration()
{
std::cout << "Aurora configuration: " << std::endl;
std::cout << "has tlast: " << has_tlast << std::endl;
std::cout << "has tkeep: " << has_tkeep << std::endl;
std::cout << "FIFO width: " << fifo_width << std::endl;
std::cout << "FIFO depth: " << fifo_depth << std::endl;
std::cout << "FIFO full threshold: " << fifo_prog_full_threshold << std::endl;
std::cout << "FIFO empty threshold: " << fifo_prog_empty_threshold << std::endl;
std::cout << "Equalization mode: " << rx_eq_mode_names[rx_eq_mode] << std::endl;
std::cout << "Nyquist loss: " << (uint16_t)ins_loss_nyq << std::endl;
}
uint32_t get_core_status()
{
return ip.read_register(CORE_STATUS_ADDRESS);
}
uint8_t gt_powergood()
{
return (get_core_status() & GT_POWERGOOD);
}
uint8_t line_up()
{
return (get_core_status() & LINE_UP) >> 4;
}
bool gt_pll_lock()
{
return (get_core_status() & GT_PLL_LOCK);
}
bool mmcm_not_locked_out()
{
return (get_core_status() & MMCM_NOT_LOCKED_OUT);
}
bool hard_err()
{
return (get_core_status() & HARD_ERR);
}
bool soft_err()
{
return (get_core_status() & SOFT_ERR);
}
bool channel_up()
{
return (get_core_status() & CHANNEL_UP);
}
void print_core_status()
{
uint32_t reg_read_data = get_core_status();
std::cout << "GT Power good: " << std::bitset<4>(reg_read_data & GT_POWERGOOD) << std::endl;
std::cout << "Lines up: " << std::bitset<4>((reg_read_data & LINE_UP) >> 4) << std::endl;
if (reg_read_data & GT_PLL_LOCK)
{
std::cout << "GT PLL Lock" << std::endl;
}
if (reg_read_data & MMCM_NOT_LOCKED_OUT)
{
std::cout << "MMCM not locked out" << std::endl;
}
if (reg_read_data & HARD_ERR)
{
std::cout << "Hard error detected" << std::endl;
}
if (reg_read_data & SOFT_ERR)
{
std::cout << "Soft error detected" << std::endl;
}
if (reg_read_data & CHANNEL_UP)
{
std::cout << "Channel up" << std::endl;
}
}
bool core_status_ok(size_t timeout_ms)
{
double timeout_start, timeout_finish;
timeout_start = get_wtime();
while (1) {
uint32_t reg_read_data = get_core_status();
if (reg_read_data == CORE_STATUS_OK) {
return true;
} else {
timeout_finish = get_wtime();
if (((timeout_finish - timeout_start) * 1000) > timeout_ms) {
return false;
}
}
}
}
uint32_t get_status_not_ok_count()
{
return ip.read_register(STATUS_NOT_OK_COUNT_ADDRESS);
}
uint32_t get_fifo_rx_overflow_count()
{
return ip.read_register(FIFO_RX_OVERFLOW_COUNT_ADDRESS);
}
uint32_t get_fifo_tx_overflow_count()
{
return ip.read_register(FIFO_TX_OVERFLOW_COUNT_ADDRESS);
}
uint32_t get_fifo_status()
{
return ip.read_register(FIFO_STATUS_ADDRESS);
}
bool fifo_tx_is_prog_empty()
{
return (get_fifo_status() & FIFO_TX_PROG_EMPTY);
}
bool fifo_tx_is_almost_empty()
{
return (get_fifo_status() & FIFO_TX_ALMOST_EMPTY);
}
bool fifo_tx_is_prog_full()
{
return (get_fifo_status() & FIFO_TX_PROG_FULL);
}
bool fifo_tx_is_almost_full()
{
return (get_fifo_status() & FIFO_TX_ALMOST_FULL);
}
bool fifo_rx_is_prog_empty()
{
return (get_fifo_status() & FIFO_RX_PROG_EMPTY);
}
bool fifo_rx_is_almost_empty()
{
return (get_fifo_status() & FIFO_RX_ALMOST_EMPTY);
}
bool fifo_rx_is_prog_full()
{
return (get_fifo_status() & FIFO_RX_PROG_FULL);
}
bool fifo_rx_is_almost_full()
{
return (get_fifo_status() & FIFO_RX_ALMOST_FULL);
}
void print_fifo_status()
{
uint32_t fifo_status = get_fifo_status();
for (uint32_t bit = 0; bit < 8; bit++) {
if (fifo_status & (1 << bit)) {
std::cout << fifo_status_name[bit] << std::endl;
}
}
}
uint32_t get_nfc_full_trigger_count()
{
return ip.read_register(NFC_FULL_TRIGGER_COUNT_ADDRESS);
}
uint32_t get_nfc_empty_trigger_count()
{
return ip.read_register(NFC_FULL_TRIGGER_COUNT_ADDRESS);
}
uint32_t get_frames_received()
{
if (has_tlast) {
return ip.read_register(FRAMES_RECEIVED_ADDRESS);
} else {
return -1;
}
}
uint32_t get_frames_with_errors()
{
if (has_tlast) {
return ip.read_register(FRAMES_WITH_ERRORS_ADDRESS);
} else {
return -1;
}
}
void set_reset(bool active)
{
ip.write_register(SW_RESET_ADDRESS, active);
}
bool has_tkeep;
bool has_tlast;
uint16_t fifo_width;
uint16_t fifo_depth;
uint8_t rx_eq_mode;
uint8_t ins_loss_nyq;
uint16_t fifo_prog_full_threshold;
uint16_t fifo_prog_empty_threshold;
private:
xrt::ip ip;
};