lorenzo_ipedma_test.c 23 KB

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