bzr branch
http://suren.me/webbzr/alps/pcitool
236
by Suren A. Chilingaryan
Big redign of model structures |
1 |
#define _POSIX_C_SOURCE 200809L
|
2 |
#define _BSD_SOURCE
|
|
227
by Suren A. Chilingaryan
Initial implementation of IPEDMA, dummy driver for KAPTURE, start of API changes |
3 |
#include <stdio.h> |
4 |
#include <stdlib.h> |
|
5 |
#include <string.h> |
|
6 |
#include <unistd.h> |
|
7 |
#include <stdarg.h> |
|
8 |
#include <time.h> |
|
9 |
#include <sched.h> |
|
10 |
#include <sys/time.h> |
|
11 |
#include <sys/types.h> |
|
12 |
#include <arpa/inet.h> |
|
13 |
#include <sched.h> |
|
14 |
#include <errno.h> |
|
15 |
||
16 |
#include "pcilib.h" |
|
17 |
#include "irq.h" |
|
18 |
#include "kmem.h" |
|
236
by Suren A. Chilingaryan
Big redign of model structures |
19 |
#include "pci.h" |
227
by Suren A. Chilingaryan
Initial implementation of IPEDMA, dummy driver for KAPTURE, start of API changes |
20 |
|
21 |
//#include <sys/ipc.h>
|
|
22 |
//#include <sys/shm.h>
|
|
23 |
||
24 |
||
25 |
#define DEVICE "/dev/fpga0"
|
|
26 |
||
27 |
#define BAR PCILIB_BAR0
|
|
28 |
#define USE_RING PCILIB_KMEM_USE(PCILIB_KMEM_USE_USER, 1)
|
|
29 |
#define USE PCILIB_KMEM_USE(PCILIB_KMEM_USE_USER, 2)
|
|
30 |
//#define STATIC_REGION 0x80000000 // to reserve 512 MB at the specified address, add "memmap=512M$2G" to kernel parameters
|
|
31 |
||
32 |
#define BUFFERS 128
|
|
33 |
#define ITERATIONS 1000
|
|
34 |
#define DESC_THRESHOLD BUFFERS/8 // Lorenzo: after how many desc the FPGA must update the "written descriptor counter" in PC mem |
|
35 |
// if set to 0, the update only happens when INT is received
|
|
36 |
||
37 |
#define HUGE_PAGE 1 // number of pages per huge page |
|
236
by Suren A. Chilingaryan
Big redign of model structures |
38 |
#define TLP_SIZE 64 // TLP SIZE = 64 for 256B payload, 32 for 128B payload |
227
by Suren A. Chilingaryan
Initial implementation of IPEDMA, dummy driver for KAPTURE, start of API changes |
39 |
#define PAGE_SIZE 4096 // other values are not supported in the kernel |
40 |
||
236
by Suren A. Chilingaryan
Big redign of model structures |
41 |
#define USE_64 // Lorenzo: use 64bit addressing |
227
by Suren A. Chilingaryan
Initial implementation of IPEDMA, dummy driver for KAPTURE, start of API changes |
42 |
|
43 |
//#define DUAL_CORE // Lorenzo: DUAL Core
|
|
44 |
||
45 |
//#define SHARED_MEMORY // Lorenzo: Test for fast GUI
|
|
46 |
||
47 |
#define CHECK_READY // Lorenzo: Check if PCI-Express is ready by reading 0x0 |
|
48 |
#define CHECK_RESULTS // Lorenzo: Check if data received is ok (only for counter!) |
|
49 |
//#define PRINT_RESULTS // Lorenzo: Save the received data in "data.out"
|
|
50 |
//#define EXIT_ON_EMPTY // Lorenzo: Exit if an "empty_detected" signal is received
|
|
51 |
||
52 |
//#define HEB // Lorenzo: Testing HEB
|
|
53 |
//#define SWITCH_GENERATOR // Lorenzo: Testing HEB -> Turn data gen on/off
|
|
54 |
||
55 |
//#define TEST_DDR // Lorenzo: Testing DDR
|
|
56 |
||
57 |
#define TIMEOUT 1000000
|
|
58 |
||
59 |
||
60 |
||
61 |
/* IRQs are slow for some reason. REALTIME mode is slower. Adding delays does not really help,
|
|
62 |
otherall we have only 3 checks in average. Check ready seems to be not needed and adds quite
|
|
63 |
much extra time */
|
|
64 |
||
65 |
//#define USE_IRQ
|
|
66 |
//#define REALTIME
|
|
67 |
//#define ADD_DELAYS
|
|
68 |
||
69 |
||
70 |
#define FPGA_CLOCK 250 // Lorenzo: in MHz ! |
|
71 |
||
72 |
||
73 |
||
74 |
//#define WR(addr, value) { val = value; pcilib_write(pci, BAR, addr, sizeof(val), &val); }
|
|
75 |
//#define RD(addr, value) { pcilib_read(pci, BAR, addr, sizeof(val), &val); value = val; }
|
|
76 |
#define WR(addr, value) { *(uint32_t*)(bar + addr + offset) = value; }
|
|
77 |
#define RD(addr, value) { value = *(uint32_t*)(bar + addr + offset); }
|
|
78 |
||
79 |
// **************************************************************************************
|
|
80 |
// Progress BAR
|
|
81 |
// Process has done x out of n rounds,
|
|
82 |
// and we want a bar of width w and resolution r.
|
|
83 |
static inline void loadBar(int x, int n, int r, int w) |
|
84 |
{
|
|
85 |
// Only update r times.
|
|
86 |
if ( x % (n/r +1) != 0 ) return; |
|
87 |
||
88 |
// Calculuate the ratio of complete-to-incomplete.
|
|
89 |
float ratio = x/(float)n; |
|
90 |
int c = ratio * w; |
|
91 |
||
92 |
// Show the percentage complete.
|
|
93 |
printf("%3d%% [", (int)(ratio*100) ); |
|
94 |
||
95 |
// Show the load bar.
|
|
96 |
for (x=0; x<c; x++) |
|
97 |
printf("="); |
|
98 |
||
99 |
for (x=c; x<w; x++) |
|
100 |
printf(" "); |
|
101 |
||
102 |
// ANSI Control codes to go back to the
|
|
103 |
// previous line and clear it.
|
|
104 |
printf("]\n\033[F\033[J"); |
|
105 |
}
|
|
106 |
// **************************************************************************************
|
|
107 |
||
108 |
||
109 |
static void fail(const char *msg, ...) { |
|
110 |
va_list va; |
|
111 |
||
112 |
va_start(va, msg); |
|
113 |
vprintf(msg, va); |
|
114 |
va_end(va); |
|
115 |
printf("\n"); |
|
116 |
||
117 |
exit(-1); |
|
118 |
}
|
|
119 |
||
120 |
void hpsleep(size_t ns) { |
|
121 |
struct timespec wait, tv; |
|
122 |
||
123 |
clock_gettime(CLOCK_REALTIME, &wait); |
|
124 |
||
125 |
wait.tv_nsec += ns; |
|
126 |
if (wait.tv_nsec > 999999999) { |
|
127 |
wait.tv_sec += 1; |
|
128 |
wait.tv_nsec = 1000000000 - wait.tv_nsec; |
|
129 |
}
|
|
130 |
||
131 |
do { |
|
132 |
clock_gettime(CLOCK_REALTIME, &tv); |
|
133 |
} while ((wait.tv_sec > tv.tv_sec)||((wait.tv_sec == tv.tv_sec)&&(wait.tv_nsec > tv.tv_nsec))); |
|
134 |
}
|
|
135 |
||
136 |
||
137 |
// **************************************************************************************
|
|
138 |
int main() { |
|
139 |
||
140 |
||
141 |
||
142 |
int err; |
|
236
by Suren A. Chilingaryan
Big redign of model structures |
143 |
int i, j, k; |
227
by Suren A. Chilingaryan
Initial implementation of IPEDMA, dummy driver for KAPTURE, start of API changes |
144 |
int mem_diff; |
145 |
pcilib_t *pci; |
|
146 |
pcilib_kmem_handle_t *kdesc; |
|
147 |
pcilib_kmem_handle_t *kbuf; |
|
148 |
struct timeval start, end; |
|
236
by Suren A. Chilingaryan
Big redign of model structures |
149 |
size_t run_time; |
150 |
size_t size_mb; |
|
227
by Suren A. Chilingaryan
Initial implementation of IPEDMA, dummy driver for KAPTURE, start of API changes |
151 |
void* volatile bar; |
152 |
uintptr_t bus_addr[BUFFERS]; |
|
153 |
uintptr_t kdesc_bus; |
|
154 |
volatile uint32_t *desc; |
|
155 |
typedef volatile uint32_t *Tbuf; |
|
156 |
Tbuf ptr[BUFFERS]; |
|
236
by Suren A. Chilingaryan
Big redign of model structures |
157 |
|
158 |
#ifdef SWITCH_GENERATOR
|
|
227
by Suren A. Chilingaryan
Initial implementation of IPEDMA, dummy driver for KAPTURE, start of API changes |
159 |
int switch_generator = 0; |
236
by Suren A. Chilingaryan
Big redign of model structures |
160 |
#endif /* SWITCH_GENERATOR */ |
161 |
||
227
by Suren A. Chilingaryan
Initial implementation of IPEDMA, dummy driver for KAPTURE, start of API changes |
162 |
float performance, perf_counter; |
163 |
pcilib_bar_t bar_tmp = BAR; |
|
164 |
uintptr_t offset = 0; |
|
165 |
||
166 |
unsigned int temp; |
|
236
by Suren A. Chilingaryan
Big redign of model structures |
167 |
unsigned iterations_completed, buffers_filled; |
227
by Suren A. Chilingaryan
Initial implementation of IPEDMA, dummy driver for KAPTURE, start of API changes |
168 |
|
169 |
||
170 |
// int shmid;
|
|
171 |
||
172 |
||
173 |
printf("\n\n**** **** **** KIT-DMA TEST **** **** ****\n\n"); |
|
174 |
||
175 |
size_mb = ITERATIONS * BUFFERS * HUGE_PAGE * 4 / 1024; |
|
176 |
printf("Total size of memory buffer: \t %.3lf GBytes\n", (float)size_mb/1024 ); |
|
236
by Suren A. Chilingaryan
Big redign of model structures |
177 |
printf("Using %u Buffers with %u iterations\n\n", BUFFERS, ITERATIONS ); |
227
by Suren A. Chilingaryan
Initial implementation of IPEDMA, dummy driver for KAPTURE, start of API changes |
178 |
|
179 |
#ifdef ADD_DELAYS
|
|
180 |
long rpt = 0, rpt2 = 0; |
|
181 |
size_t best_time; |
|
182 |
best_time = 1000000000L * HUGE_PAGE * PAGE_SIZE / (4L * 1024 * 1024 * 1024); |
|
183 |
#endif /* ADD_DELAYS */ |
|
184 |
||
185 |
||
186 |
pcilib_kmem_flags_t flags = PCILIB_KMEM_FLAG_HARDWARE|PCILIB_KMEM_FLAG_PERSISTENT|PCILIB_KMEM_FLAG_EXCLUSIVE/*|PCILIB_KMEM_FLAG_REUSE*/; // Lorenzo: if REUSE = 1, the re-allocation fails! |
|
187 |
pcilib_kmem_flags_t free_flags = PCILIB_KMEM_FLAG_HARDWARE/*|PCILIB_KMEM_FLAG_EXCLUSIVE|PCILIB_KMEM_FLAG_REUSE*/; |
|
188 |
pcilib_kmem_flags_t clean_flags = PCILIB_KMEM_FLAG_HARDWARE|PCILIB_KMEM_FLAG_PERSISTENT|PCILIB_KMEM_FLAG_EXCLUSIVE; |
|
189 |
||
190 |
pci = pcilib_open(DEVICE, PCILIB_MODEL_DETECT); |
|
191 |
if (!pci) fail("pcilib_open"); |
|
192 |
||
193 |
bar = pcilib_map_bar(pci, BAR); |
|
194 |
if (!bar) { |
|
195 |
pcilib_close(pci); |
|
196 |
fail("map bar"); |
|
197 |
}
|
|
198 |
||
199 |
pcilib_detect_address(pci, &bar_tmp, &offset, 1); |
|
200 |
||
201 |
pcilib_enable_irq(pci, PCILIB_IRQ_TYPE_ALL, 0); |
|
202 |
pcilib_clear_irq(pci, PCILIB_IRQ_SOURCE_DEFAULT); |
|
203 |
||
204 |
pcilib_clean_kernel_memory(pci, USE, clean_flags); |
|
205 |
pcilib_clean_kernel_memory(pci, USE_RING, clean_flags); |
|
206 |
||
207 |
kdesc = pcilib_alloc_kernel_memory(pci, PCILIB_KMEM_TYPE_CONSISTENT, 1, 128, 4096, USE_RING, flags); |
|
208 |
kdesc_bus = pcilib_kmem_get_block_ba(pci, kdesc, 0); |
|
209 |
desc = (uint32_t*)pcilib_kmem_get_block_ua(pci, kdesc, 0); |
|
210 |
memset((void*)desc, 0, 5*sizeof(uint32_t)); |
|
211 |
||
212 |
#ifdef REALTIME
|
|
213 |
pid_t pid; |
|
214 |
struct sched_param sched = {0}; |
|
215 |
||
216 |
pid = getpid(); |
|
217 |
sched.sched_priority = sched_get_priority_min(SCHED_FIFO); |
|
218 |
if (sched_setscheduler(pid, SCHED_FIFO, &sched)) |
|
219 |
printf("Warning: not able to get real-time priority\n"); |
|
220 |
#endif /* REALTIME */ |
|
221 |
||
222 |
// ******************************************************************
|
|
223 |
// **** MEM: check 4k boundary *****
|
|
224 |
// ******************************************************************
|
|
225 |
||
226 |
do { |
|
227 |
printf("* Allocating KMem, "); |
|
228 |
#ifdef STATIC_REGION
|
|
229 |
kbuf = pcilib_alloc_kernel_memory(pci, PCILIB_KMEM_TYPE_REGION_C2S, BUFFERS, HUGE_PAGE * PAGE_SIZE, STATIC_REGION, USE, flags); |
|
230 |
#else
|
|
231 |
kbuf = pcilib_alloc_kernel_memory(pci, PCILIB_KMEM_TYPE_DMA_C2S_PAGE, BUFFERS, HUGE_PAGE * PAGE_SIZE, 4096, USE, flags); |
|
232 |
#endif
|
|
233 |
||
234 |
if (!kbuf) { |
|
235 |
printf("KMem allocation failed\n"); |
|
236 |
exit(0); |
|
237 |
}
|
|
238 |
||
239 |
// Pointers for Virtualized Mem
|
|
240 |
for (j = 0; j < BUFFERS; j++) { |
|
241 |
ptr[j] = (volatile uint32_t*)pcilib_kmem_get_block_ua(pci, kbuf, j); |
|
236
by Suren A. Chilingaryan
Big redign of model structures |
242 |
memset((void*)ptr[j], 0, HUGE_PAGE * PAGE_SIZE); |
227
by Suren A. Chilingaryan
Initial implementation of IPEDMA, dummy driver for KAPTURE, start of API changes |
243 |
}
|
244 |
||
245 |
err = 0; |
|
246 |
||
247 |
// Check if HW addresses satisfy 4k boundary condition, if not -> free (!!) and reallocate memory
|
|
248 |
printf("4k boundary test: "); |
|
249 |
for (j = 0; j < BUFFERS; j++) { |
|
250 |
temp = (((unsigned int)pcilib_kmem_get_block_ba(pci, kbuf, j)) % 4096); |
|
251 |
//printf("%u", temp);
|
|
252 |
if (temp != 0) { |
|
253 |
err = 1; |
|
254 |
}
|
|
255 |
}
|
|
256 |
if (err == 1) { |
|
257 |
pcilib_clean_kernel_memory(pci, USE, clean_flags); |
|
258 |
pcilib_clean_kernel_memory(pci, USE_RING, clean_flags); |
|
259 |
pcilib_free_kernel_memory(pci, kbuf, free_flags); |
|
260 |
printf("failed \xE2\x9C\x98\n"); |
|
261 |
}
|
|
262 |
else printf("passed \xE2\x9C\x93\n"); |
|
263 |
||
264 |
} while (err == 1); |
|
265 |
||
266 |
||
267 |
// ******************************************************************
|
|
268 |
// **** Allocate RAM buffer Memory *****
|
|
269 |
// ******************************************************************
|
|
270 |
||
271 |
FILE * Output; |
|
272 |
FILE * error_log; |
|
273 |
||
274 |
#ifdef CHECK_RESULTS
|
|
275 |
uint32_t *temp_data[ITERATIONS][BUFFERS]; |
|
276 |
||
277 |
for (j=0; j < ITERATIONS; j++) { |
|
278 |
for (i=0; i < BUFFERS; i++) { |
|
279 |
temp_data[j][i] = (uint32_t *)malloc(HUGE_PAGE*PAGE_SIZE); |
|
280 |
if (temp_data[j][i] == 0) { |
|
281 |
printf("******* Error: could not allocate memory! ********\n"); |
|
282 |
exit(0); |
|
283 |
}
|
|
284 |
memset((void*)(temp_data[j][i]), 0, HUGE_PAGE * PAGE_SIZE); |
|
285 |
}
|
|
286 |
}
|
|
287 |
#endif
|
|
288 |
||
289 |
#ifdef SHARED_MEMORY
|
|
290 |
// give your shared memory an id, anything will do
|
|
291 |
key_t key = 123456; |
|
292 |
char *shared_memory; |
|
293 |
||
294 |
// Setup shared memory, 11 is the size
|
|
295 |
/* if ((shmid = shmget(key, HUGE_PAGE*PAGE_SIZE, IPC_CREAT | 0666)) < 0)
|
|
296 |
{
|
|
297 |
printf("Error getting shared memory id");
|
|
298 |
exit(1);
|
|
299 |
}
|
|
300 |
||
301 |
// Attached shared memory
|
|
302 |
if ((shared_memory = shmat(shmid, NULL, 0)) == (char *) -1)
|
|
303 |
{
|
|
304 |
printf("Error attaching shared memory id");
|
|
305 |
exit(1);
|
|
306 |
}
|
|
307 |
printf("* Shared memory created... Id:\t %d\n", key);
|
|
308 |
//////////////// SHARED MEMORY TEST */
|
|
309 |
#endif
|
|
310 |
||
311 |
Output = fopen ("data.out", "w"); |
|
312 |
fclose(Output); |
|
313 |
||
314 |
error_log = fopen ("error_log.txt", "w"); |
|
315 |
fclose(error_log); |
|
316 |
||
317 |
// *************************************
|
|
318 |
Output = fopen("data.txt", "w"); |
|
319 |
fclose(Output); |
|
320 |
||
321 |
// ******************************************************************
|
|
322 |
// **** PCIe TEST *****
|
|
323 |
// ******************************************************************
|
|
324 |
||
325 |
// Reset DMA
|
|
326 |
printf("* DMA: Reset...\n"); |
|
327 |
WR(0x00, 0x1); |
|
328 |
usleep(100000); |
|
329 |
WR(0x00, 0x0); |
|
330 |
usleep(100000); |
|
331 |
||
332 |
#ifdef CHECK_READY
|
|
333 |
printf("* PCIe: Testing..."); |
|
334 |
RD(0x0, err); |
|
236
by Suren A. Chilingaryan
Big redign of model structures |
335 |
if (err == 335746816 || err == 335681280) { |
336 |
printf("\xE2\x9C\x93 \n"); |
|
337 |
} else { |
|
227
by Suren A. Chilingaryan
Initial implementation of IPEDMA, dummy driver for KAPTURE, start of API changes |
338 |
printf("\xE2\x9C\x98\n PCIe not ready!\n"); |
339 |
exit(0); |
|
340 |
}
|
|
341 |
#endif
|
|
342 |
||
343 |
||
344 |
// ******************************************************************
|
|
345 |
// **** DMA CONFIGURATION *****
|
|
346 |
// ******************************************************************
|
|
347 |
||
348 |
||
349 |
printf("* DMA: Start Data Generator...\n"); |
|
350 |
WR(0x04, 0x10) // Start data generator |
|
351 |
||
352 |
printf("* DMA: Send Data Fill Pattern 55aa55aa\n"); |
|
353 |
WR(0x14, 0xbeef); |
|
354 |
||
355 |
printf("* DMA: Send Data Amount\n"); |
|
356 |
#ifdef DUAL_CORE
|
|
357 |
WR(0x10, (HUGE_PAGE * (PAGE_SIZE / (4 * TLP_SIZE)))/2); |
|
358 |
#else
|
|
359 |
WR(0x10, (HUGE_PAGE * (PAGE_SIZE / (4 * TLP_SIZE)))); |
|
360 |
#endif
|
|
361 |
||
362 |
printf("* DMA: Running mode: "); |
|
363 |
#ifdef USE_64
|
|
364 |
if (TLP_SIZE == 64) |
|
365 |
{
|
|
366 |
WR(0x0C, 0x80040); |
|
367 |
printf ("64bit - 256B Payload\n"); |
|
368 |
}
|
|
369 |
else if (TLP_SIZE == 32) |
|
370 |
{
|
|
371 |
WR(0x0C, 0x80020); |
|
372 |
printf ("64bit - 128B Payload\n"); |
|
373 |
}
|
|
374 |
#else
|
|
375 |
if (TLP_SIZE == 64) |
|
376 |
{
|
|
377 |
WR(0x0C, 0x0040); |
|
378 |
printf ("32bit - 256B Payload\n"); |
|
379 |
}
|
|
380 |
else if (TLP_SIZE == 32) |
|
381 |
{
|
|
382 |
WR(0x0C, 0x0020); |
|
383 |
printf ("32bit - 128B Payload\n"); |
|
384 |
}
|
|
385 |
#endif
|
|
386 |
||
387 |
printf("* DMA: Reset Desc Memory...\n"); |
|
388 |
WR(0x5C, 0x00); // RST Desc Memory |
|
389 |
||
390 |
//printf("Writing SW Read Descriptor\n");
|
|
391 |
WR(0x58, BUFFERS-1); |
|
392 |
//WR(0x58, 0x01);
|
|
393 |
||
394 |
//printf("Writing the Descriptor Threshold\n");
|
|
395 |
WR(0x60, DESC_THRESHOLD); |
|
396 |
||
397 |
//printf("Writing HW write Descriptor Address: %lx\n", kdesc_bus);
|
|
398 |
WR(0x54, kdesc_bus); |
|
399 |
usleep(100000); |
|
400 |
||
401 |
printf("* DMA: Writing Descriptors\n"); |
|
402 |
for (j = 0; j < BUFFERS; j++ ) { |
|
403 |
bus_addr[j] = pcilib_kmem_get_block_ba(pci, kbuf, j); |
|
404 |
// LEAVE THIS DELAY???!?!?!?!
|
|
405 |
usleep(1000); |
|
236
by Suren A. Chilingaryan
Big redign of model structures |
406 |
printf("Writing descriptor num. %d: \t %08lx \r", j, bus_addr[j]); |
227
by Suren A. Chilingaryan
Initial implementation of IPEDMA, dummy driver for KAPTURE, start of API changes |
407 |
WR(0x50, bus_addr[j]); |
408 |
}
|
|
409 |
||
410 |
// ******************************************************************
|
|
411 |
// **** HEB CONFIGURATION *****
|
|
412 |
// ******************************************************************
|
|
413 |
#ifdef HEB
|
|
414 |
||
415 |
||
416 |
printf("* DDR REGISTERS: AXI_BUF_SIZE \n"); |
|
417 |
WR(0x9130, 0x1000); |
|
418 |
||
419 |
usleep(100000); |
|
420 |
||
421 |
printf("* HEB: Control \n"); |
|
422 |
WR(0x9040, 0x00000001); |
|
423 |
||
424 |
usleep(100000); |
|
425 |
||
426 |
printf("* HEB: Control \n"); |
|
427 |
WR(0x9040, 0x00000004); |
|
428 |
||
429 |
usleep(100000); |
|
430 |
||
431 |
printf("* HEB: Control \n"); |
|
432 |
WR(0x9040, 0x00000000); |
|
433 |
||
434 |
usleep(100000); |
|
435 |
||
436 |
printf("* HEB: Writing Total Orbit Num\n"); |
|
437 |
WR(0x9020, 0x2000); |
|
438 |
||
439 |
printf("* HEB: Orbit Skip Num h9028\n"); |
|
440 |
WR(0x9028, 0x4); |
|
441 |
||
442 |
//printf("* HEB: LVDS_DELAY h9080\n");
|
|
443 |
//WR(0x9080, 0x10101010);
|
|
444 |
||
445 |
//printf("* HEB: Delay ADCs \n");
|
|
446 |
//WR(0x9088, 0x001);
|
|
447 |
//WR(0x9090, 0x001);
|
|
448 |
//WR(0x9094, 0x001);
|
|
449 |
//WR(0x9098, 0x001);
|
|
450 |
||
451 |
//printf("* HEB: Delay TH \n");
|
|
452 |
//WR(0x90a0, 0x005);
|
|
453 |
||
454 |
//printf("* HEB: Delay_FPGA_reg \n");
|
|
455 |
//WR(0x90a8, 0x006);
|
|
456 |
||
457 |
//printf("* HEB: Control \n");
|
|
458 |
//WR(0x9040, 0x40000000);
|
|
459 |
||
460 |
//usleep(1000000);
|
|
461 |
||
462 |
printf("* HEB: Control \n"); |
|
463 |
WR(0x9040, 0x40000bf0); |
|
464 |
||
465 |
usleep(100000); |
|
466 |
||
467 |
printf("* HEB: Control \n"); |
|
468 |
WR(0x9040, 0x400003f0); |
|
469 |
||
470 |
usleep(100000); |
|
471 |
||
472 |
printf("* HEB: Control \n"); |
|
473 |
WR(0x9040, 0x480007F0); |
|
474 |
||
475 |
usleep(100000); |
|
476 |
||
477 |
printf("* HEB: Control \n"); |
|
478 |
WR(0x9040, 0x48000FF0); |
|
479 |
||
480 |
||
481 |
#endif
|
|
482 |
||
483 |
// ******************************************************************
|
|
484 |
// **** TEST DDR conf *****
|
|
485 |
// ******************************************************************
|
|
486 |
#ifdef TEST_DDR
|
|
487 |
||
488 |
||
489 |
printf("* DDR: AXI_BUF_SIZE_ADDR: 4k\n"); |
|
490 |
WR(0x9010, 0x04000); |
|
491 |
||
492 |
printf("* DDR: Control \n"); |
|
493 |
WR(0x9000, 0x000000F); |
|
494 |
||
495 |
usleep(100000); |
|
496 |
WR(0x9000, 0x00000008); |
|
497 |
usleep(100000); |
|
498 |
WR(0x9000, 0x08000008); |
|
499 |
||
500 |
usleep(50000); |
|
501 |
||
502 |
printf("* DDR: Control \n"); |
|
503 |
WR(0x9000, 0x08000208); |
|
504 |
||
505 |
||
506 |
#endif
|
|
507 |
||
508 |
// ******************************************************************
|
|
509 |
// **** START DMA *****
|
|
510 |
// ******************************************************************
|
|
511 |
||
512 |
//printf ("\n ---- Press ENTER to start DMA ---- \n");
|
|
513 |
//getchar();
|
|
514 |
||
515 |
printf("* DMA: Start \n"); |
|
516 |
WR(0x04, 0x1f); |
|
517 |
gettimeofday(&start, NULL); |
|
518 |
||
519 |
// ******************************************************************
|
|
520 |
// **** Handshaking DMA *****
|
|
521 |
// ******************************************************************
|
|
522 |
||
523 |
uint32_t curptr = 0, hwptr; |
|
524 |
uint32_t curbuf = 0; |
|
525 |
int empty = 0; |
|
526 |
i = 0; |
|
527 |
||
528 |
||
529 |
while (i < ITERATIONS) { |
|
530 |
j = 0; |
|
531 |
// printf("\ndesc0: %lx", htonl(desc[0]));
|
|
532 |
// printf("\ndesc1: %lx", htonl(desc[1]));
|
|
533 |
// printf("\ndesc2: %lx", htonl(desc[2]));
|
|
534 |
// printf("\ndesc3: %lx", htonl(desc[3]));
|
|
535 |
// printf("\ndesc4: %lx", htonl(desc[4]));
|
|
536 |
// printf("\ndesc5: %lx", htonl(desc[5]));
|
|
537 |
//printf("Iteration: %li of %li \r", i+1, ITERATIONS);
|
|
538 |
//loadBar(i+1, ITERATIONS, ITERATIONS, 30);
|
|
539 |
// printf("\nhwptr: %zu", hwptr);
|
|
540 |
// printf("\ncurptr: %zu", curptr);
|
|
541 |
||
542 |
do { |
|
543 |
#ifdef USE_64
|
|
236
by Suren A. Chilingaryan
Big redign of model structures |
544 |
hwptr = desc[3]; |
227
by Suren A. Chilingaryan
Initial implementation of IPEDMA, dummy driver for KAPTURE, start of API changes |
545 |
#else // 32-bit |
236
by Suren A. Chilingaryan
Big redign of model structures |
546 |
hwptr = desc[4]; |
227
by Suren A. Chilingaryan
Initial implementation of IPEDMA, dummy driver for KAPTURE, start of API changes |
547 |
#endif
|
548 |
j++; |
|
549 |
//printf("\rcurptr: %lx \t \t hwptr: %lx", curptr, hwptr);
|
|
550 |
} while (hwptr == curptr); |
|
551 |
||
552 |
do { |
|
553 |
pcilib_kmem_sync_block(pci, kbuf, PCILIB_KMEM_SYNC_FROMDEVICE, curbuf); |
|
554 |
#ifdef CHECK_RESULTS
|
|
236
by Suren A. Chilingaryan
Big redign of model structures |
555 |
memcpy(temp_data[i][curbuf], (void*)ptr[curbuf], 4096); |
227
by Suren A. Chilingaryan
Initial implementation of IPEDMA, dummy driver for KAPTURE, start of API changes |
556 |
#endif
|
557 |
#ifdef SHARED_MEMORY
|
|
236
by Suren A. Chilingaryan
Big redign of model structures |
558 |
memcpy(shared_memory, (void*)ptr[curbuf], 4096); |
227
by Suren A. Chilingaryan
Initial implementation of IPEDMA, dummy driver for KAPTURE, start of API changes |
559 |
#endif
|
560 |
//printf("\ncurbuf: %08x", curbuf);
|
|
561 |
//printf("\nbus_addr[curbuf]\n: %08x",bus_addr[curbuf]);
|
|
562 |
// for (k = 0; k < 63; k++){
|
|
563 |
// if (k%16 == 0) printf("\n# %d # :", k);
|
|
564 |
// printf(" %08x", ptr[curbuf][k]);
|
|
565 |
// }
|
|
566 |
//pcilib_kmem_sync_block(pci, kbuf, PCILIB_KMEM_SYNC_TODEVICE, curbuf);
|
|
567 |
curbuf++; |
|
568 |
if (curbuf == BUFFERS) { |
|
569 |
i++; |
|
570 |
curbuf = 0; |
|
571 |
#ifdef SWITCH_GENERATOR
|
|
572 |
if (switch_generator == 1) { |
|
573 |
switch_generator = 0; |
|
574 |
WR(0x9040, 0x100007F0); |
|
575 |
} else { |
|
576 |
WR(0x9040, 0x180007F0); |
|
577 |
switch_generator = 1; |
|
578 |
}
|
|
579 |
#endif
|
|
580 |
if (i >= ITERATIONS) break; |
|
581 |
//if (i >= (ITERATIONS - 4) ) WR(0x04, 0x0f);
|
|
582 |
}
|
|
583 |
} while (bus_addr[curbuf] != hwptr); |
|
584 |
||
585 |
#ifdef EXIT_ON_EMPTY
|
|
586 |
#ifdef USE_64
|
|
587 |
if (desc[1] != 0) |
|
588 |
#else // 32bit |
|
589 |
if (desc[2] != 0) |
|
590 |
#endif
|
|
591 |
{
|
|
592 |
if (bus_addr[curbuf] == hwptr) { |
|
593 |
empty = 1; |
|
594 |
break; |
|
595 |
}
|
|
596 |
}
|
|
597 |
#endif
|
|
598 |
||
599 |
WR(0x58, curbuf + 1); |
|
600 |
//printf("WR %d\n", curbuf + 1);
|
|
601 |
//printf("%u (%lu)\n", curbuf, j);
|
|
602 |
curptr = hwptr; |
|
603 |
||
604 |
}
|
|
605 |
||
606 |
||
607 |
||
608 |
// ******************************************************************
|
|
609 |
// **** Read performance and stop DMA *******
|
|
610 |
// ******************************************************************
|
|
611 |
||
612 |
gettimeofday(&end, NULL); |
|
613 |
WR(0x04, 0x00); |
|
614 |
WR(0x01, 0x00); |
|
615 |
RD(0x28, perf_counter); |
|
616 |
||
617 |
||
618 |
||
619 |
iterations_completed = i; |
|
620 |
buffers_filled = curbuf; |
|
236
by Suren A. Chilingaryan
Big redign of model structures |
621 |
if (empty) printf("* DMA: Empty FIFO! Last iteration: %u of %u\n", i+1, ITERATIONS); |
227
by Suren A. Chilingaryan
Initial implementation of IPEDMA, dummy driver for KAPTURE, start of API changes |
622 |
printf ("* DMA: Stop\n\n"); |
623 |
||
624 |
#ifdef CHECK_RESULTS
|
|
625 |
printf ("First value:\t %08x\n", temp_data[0][0][0]); |
|
626 |
printf ("Last value:\t %08x\n\n", temp_data[ITERATIONS-1][BUFFERS-1][(PAGE_SIZE/4)-4]); |
|
627 |
#endif
|
|
628 |
||
629 |
// ******************************************************************
|
|
630 |
// **** Performance *******
|
|
631 |
// ******************************************************************
|
|
632 |
printf("Iterations done: %d\n", iterations_completed); |
|
633 |
printf("Buffers filled on last iteration: %d\n", buffers_filled); |
|
634 |
||
635 |
||
636 |
run_time = (end.tv_sec - start.tv_sec) * 1000000 + (end.tv_usec - start.tv_usec); |
|
637 |
size_mb = (long long int) (( BUFFERS * (iterations_completed) + buffers_filled) * HUGE_PAGE * 4 / 1024); |
|
236
by Suren A. Chilingaryan
Big redign of model structures |
638 |
printf("Performance: transfered %zu Mbytes in %zu us using %u buffers\n", (size_mb), run_time, BUFFERS); |
227
by Suren A. Chilingaryan
Initial implementation of IPEDMA, dummy driver for KAPTURE, start of API changes |
639 |
//printf("Buffers: \t %d \n", BUFFERS);
|
640 |
//printf("Buf_Size: \t %d \n", PAGE_SIZE);
|
|
641 |
//printf("Perf_counter: \t %f \n", perf_counter);
|
|
642 |
performance = ((size_mb * FPGA_CLOCK * 1000000)/(perf_counter*256)); |
|
643 |
printf("DMA perf counter:\t%d\n", (int)perf_counter); |
|
644 |
printf("DMA side:\t\t%.3lf MB/s\n", performance); |
|
645 |
printf("PC side:\t\t%.3lf MB/s\n\n", 1000000. * size_mb / run_time ); |
|
646 |
||
647 |
// ******************************************************************
|
|
648 |
// **** Read Data *******
|
|
649 |
// ******************************************************************
|
|
650 |
||
651 |
||
236
by Suren A. Chilingaryan
Big redign of model structures |
652 |
#ifdef PRINT_RESULTS
|
227
by Suren A. Chilingaryan
Initial implementation of IPEDMA, dummy driver for KAPTURE, start of API changes |
653 |
printf("Writing Data to HDD... \n"); |
654 |
for (i=0; i < iterations_completed; i++) { |
|
655 |
for (j=0; j < BUFFERS; j++) |
|
656 |
{
|
|
657 |
Output = fopen("data.out", "a"); |
|
658 |
fwrite(temp_data[i][j], 4096, 1, Output); |
|
659 |
fclose(Output); |
|
660 |
}
|
|
661 |
loadBar(i+1, ITERATIONS, ITERATIONS, 30); |
|
662 |
}
|
|
663 |
// Save last partially filled iteration
|
|
664 |
for (j=0; j < buffers_filled; j++) |
|
665 |
{
|
|
666 |
Output = fopen("data.out", "a"); |
|
667 |
fwrite(temp_data[iterations_completed][j], 4096, 1, Output); |
|
668 |
fclose(Output); |
|
669 |
}
|
|
670 |
printf("Data saved in data.out. \n"); |
|
236
by Suren A. Chilingaryan
Big redign of model structures |
671 |
#endif
|
227
by Suren A. Chilingaryan
Initial implementation of IPEDMA, dummy driver for KAPTURE, start of API changes |
672 |
|
236
by Suren A. Chilingaryan
Big redign of model structures |
673 |
#ifdef CHECK_RESULTS
|
227
by Suren A. Chilingaryan
Initial implementation of IPEDMA, dummy driver for KAPTURE, start of API changes |
674 |
err = 0; |
675 |
error_log = fopen ("error_log.txt", "a"); |
|
676 |
printf("\nChecking data ...\n"); |
|
677 |
for (i=0; i < iterations_completed; i++) { |
|
678 |
for (j = 0; j < BUFFERS; j++) { |
|
679 |
for (k = 0; k < 1024 ; k++) |
|
680 |
{
|
|
681 |
mem_diff = ((uint32_t)temp_data[i][j][k] - (uint32_t)temp_data[i][j][k+1]); |
|
682 |
//if ((mem_diff == 1) || (mem_diff == (-7)) || (k == 1023) )
|
|
683 |
if ((mem_diff == -1) || (k == 1023) ) |
|
684 |
{;}
|
|
685 |
else { |
|
236
by Suren A. Chilingaryan
Big redign of model structures |
686 |
fprintf(error_log, "Error in: \t IT %u \t BUF : %u \t OFFSET: %u \t | %08x --> %08x - DIFF: %d \n", i, j, k, temp_data[i][j][k], temp_data[i][j][k+1], mem_diff); |
227
by Suren A. Chilingaryan
Initial implementation of IPEDMA, dummy driver for KAPTURE, start of API changes |
687 |
err++; |
688 |
}
|
|
689 |
}
|
|
690 |
if (j != BUFFERS-1) { |
|
691 |
// Check first and Last
|
|
692 |
mem_diff = (uint32_t)(temp_data[i][j+1][0] - temp_data[i][j][1023]); |
|
693 |
if (mem_diff == (1)) |
|
694 |
{;}
|
|
695 |
else { |
|
236
by Suren A. Chilingaryan
Big redign of model structures |
696 |
fprintf(error_log, "Error_2 in: \t IT %u \t BUF : %u \t OFFSET: %u \t | %08x --> %08x - DIFF: %d \n", i, j, k, temp_data[i][j+1][0], temp_data[i][j][1023], mem_diff); |
227
by Suren A. Chilingaryan
Initial implementation of IPEDMA, dummy driver for KAPTURE, start of API changes |
697 |
err++; |
698 |
}
|
|
699 |
}
|
|
700 |
||
701 |
}
|
|
702 |
loadBar(i+1, ITERATIONS, ITERATIONS, 30); |
|
703 |
}
|
|
704 |
for (j = 0; j < buffers_filled; j++) { |
|
236
by Suren A. Chilingaryan
Big redign of model structures |
705 |
for (k = 0; k < 1024 ; k++) { |
227
by Suren A. Chilingaryan
Initial implementation of IPEDMA, dummy driver for KAPTURE, start of API changes |
706 |
mem_diff = ((uint32_t)temp_data[iterations_completed][j][k] - (uint32_t)temp_data[iterations_completed][j][k+1]); |
236
by Suren A. Chilingaryan
Big redign of model structures |
707 |
if ((mem_diff == -1) || (k == 1023) ) { |
708 |
;
|
|
709 |
} else { |
|
710 |
fprintf(error_log, "Error in: \t IT %u \t BUF : %u \t OFFSET: %u \t | %08x --> %08x - DIFF: %d \n", iterations_completed, j, k, temp_data[iterations_completed][j][k], temp_data[iterations_completed][j][k+1], mem_diff); |
|
227
by Suren A. Chilingaryan
Initial implementation of IPEDMA, dummy driver for KAPTURE, start of API changes |
711 |
err++; |
712 |
}
|
|
713 |
}
|
|
236
by Suren A. Chilingaryan
Big redign of model structures |
714 |
if (j < (buffers_filled-1)) { |
227
by Suren A. Chilingaryan
Initial implementation of IPEDMA, dummy driver for KAPTURE, start of API changes |
715 |
// Check first and Last
|
716 |
mem_diff = (uint32_t)(temp_data[i][j+1][0] - temp_data[i][j][1023]); |
|
236
by Suren A. Chilingaryan
Big redign of model structures |
717 |
if (mem_diff == (1)) { |
718 |
;
|
|
719 |
} else { |
|
720 |
fprintf(error_log, "Error_2 in: \t IT %u \t BUF : %u \t OFFSET: %u \t | %08x --> %08x - DIFF: %d \n", iterations_completed, j, k, temp_data[iterations_completed][j+1][0], temp_data[iterations_completed][j][1023], mem_diff); |
|
227
by Suren A. Chilingaryan
Initial implementation of IPEDMA, dummy driver for KAPTURE, start of API changes |
721 |
err++; |
722 |
}
|
|
723 |
}
|
|
724 |
}
|
|
725 |
if (err != 0) printf("\rChecking data: \xE2\x9C\x98 %d errors found \n See \"error_log.txt\" for details \n\n", err); |
|
726 |
else printf("\rChecking data: \xE2\x9C\x93 no errors found \n\n"); |
|
727 |
fclose(error_log); |
|
236
by Suren A. Chilingaryan
Big redign of model structures |
728 |
#endif
|
227
by Suren A. Chilingaryan
Initial implementation of IPEDMA, dummy driver for KAPTURE, start of API changes |
729 |
|
730 |
||
731 |
// *********** Free Memory
|
|
732 |
#ifdef CHECK_RESULTS
|
|
733 |
for (i=0; i < ITERATIONS; i++) { |
|
734 |
for (j=0; j < BUFFERS; j++) |
|
735 |
{
|
|
736 |
free(temp_data[i][j]); |
|
737 |
}
|
|
738 |
}
|
|
236
by Suren A. Chilingaryan
Big redign of model structures |
739 |
#endif /* CHECK_RESULTS */ |
227
by Suren A. Chilingaryan
Initial implementation of IPEDMA, dummy driver for KAPTURE, start of API changes |
740 |
|
741 |
pcilib_free_kernel_memory(pci, kbuf, free_flags); |
|
742 |
pcilib_free_kernel_memory(pci, kdesc, free_flags); |
|
743 |
pcilib_disable_irq(pci, 0); |
|
744 |
pcilib_unmap_bar(pci, BAR, bar); |
|
745 |
pcilib_close(pci); |
|
746 |
||
747 |
// shmdt(shmid);
|
|
748 |
// shmctl(shmid, IPC_RMID, NULL);
|
|
749 |
||
750 |
}
|