2
#define _POSIX_C_SOURCE 199309L
16
#define DEVICE "/dev/fpga0"
17
#define BAR PCILIB_BAR0
18
#define USE PCILIB_KMEM_USE(PCILIB_KMEM_USE_USER, 1)
19
#define STATIC_REGION 0x80000000 // to reserve 512 MB at the specified address, add "memmap=512M$2G" to kernel parameters
21
#define ITERATIONS 100
23
#define HUGE_PAGE 4096 // number of pages per huge page
24
#define PAGE_SIZE 4096 // other values are not supported in the kernel
25
#define TIMEOUT 100000
27
/* IRQs are slow for some reason. REALTIME mode is slower. Adding delays does not really help,
28
otherall we have only 3 checks in average. Check ready seems to be not needed and adds quite
36
//#define WR(addr, value) { val = value; pcilib_write(pci, BAR, addr, sizeof(val), &val); }
37
//#define RD(addr, value) { pcilib_read(pci, BAR, addr, sizeof(val), &val); value = val; }
38
#define WR(addr, value) { *(uint32_t*)(bar + addr + offset) = value; }
39
#define RD(addr, value) { value = *(uint32_t*)(bar + addr + offset); }
41
static void fail(const char *msg, ...) {
52
void hpsleep(size_t ns) {
53
struct timespec wait, tv;
55
clock_gettime(CLOCK_REALTIME, &wait);
58
if (wait.tv_nsec > 999999999) {
60
wait.tv_nsec = 1000000000 - wait.tv_nsec;
64
clock_gettime(CLOCK_REALTIME, &tv);
65
} while ((wait.tv_sec > tv.tv_sec)||((wait.tv_sec == tv.tv_sec)&&(wait.tv_nsec > tv.tv_nsec)));
73
pcilib_kmem_handle_t *kbuf;
75
struct timeval start, end;
76
size_t size, run_time;
78
uintptr_t bus_addr[BUFFERS];
80
pcilib_bar_t bar_tmp = BAR;
83
pcilib_kmem_flags_t clean_flags = PCILIB_KMEM_FLAG_HARDWARE|PCILIB_KMEM_FLAG_PERSISTENT|PCILIB_KMEM_FLAG_EXCLUSIVE;
86
long rpt = 0, rpt2 = 0;
88
best_time = 1000000000L * HUGE_PAGE * PAGE_SIZE / (4L * 1024 * 1024 * 1024);
89
#endif /* ADD_DELAYS */
93
struct sched_param sched = {0};
96
sched.sched_priority = sched_get_priority_min(SCHED_FIFO);
97
if (sched_setscheduler(pid, SCHED_FIFO, &sched))
98
printf("Warning: not able to get real-time priority\n");
101
pci = pcilib_open(DEVICE, PCILIB_MODEL_DETECT);
102
if (!pci) fail("pcilib_open");
104
bar = pcilib_map_bar(pci, BAR);
110
pcilib_detect_address(pci, &bar_tmp, &offset, 1);
117
pcilib_enable_irq(pci, PCILIB_IRQ_TYPE_ALL, 0);
118
pcilib_clear_irq(pci, PCILIB_IRQ_SOURCE_DEFAULT);
120
pcilib_clean_kernel_memory(pci, USE, clean_flags);
123
kbuf = pcilib_alloc_kernel_memory(pci, PCILIB_KMEM_TYPE_REGION_C2S, BUFFERS, HUGE_PAGE * PAGE_SIZE, STATIC_REGION, USE, 0);
124
#else /* STATIC_REGION */
125
kbuf = pcilib_alloc_kernel_memory(pci, PCILIB_KMEM_TYPE_DMA_C2S_PAGE, BUFFERS, HUGE_PAGE * PAGE_SIZE, 4096, USE, 0);
126
#endif /* STATIC_REGION */
129
printf("KMem allocation failed\n");
135
volatile uint32_t *ptr0 = pcilib_kmem_get_block_ua(pci, kbuf, 0);
137
memset((void*)ptr0, 0, (HUGE_PAGE * PAGE_SIZE));
139
for (i = 0; i < (HUGE_PAGE * PAGE_SIZE / 4); i++) {
140
if (ptr0[i] != 0) break;
142
if (i < (HUGE_PAGE * PAGE_SIZE / 4)) {
143
printf("Initialization error in position %lu, value = %x\n", i * 4, ptr0[i]);
145
#endif /* CHECK_RESULT */
149
WR(0x10, (HUGE_PAGE * (PAGE_SIZE / (4 * TLP_SIZE))))
152
for (j = 0; j < BUFFERS; j++ ) {
153
bus_addr[j] = pcilib_kmem_get_block_ba(pci, kbuf, j);
156
gettimeofday(&start, NULL);
158
for (i = 0; i < ITERATIONS; i++) {
159
for (j = 0; j < BUFFERS; j++ ) {
160
// uintptr_t ba = pcilib_kmem_get_block_ba(pci, kbuf, j);
162
WR(0x08, bus_addr[j]);
166
err = pcilib_wait_irq(pci, PCILIB_IRQ_SOURCE_DEFAULT, TIMEOUT, NULL);
167
if (err) printf("Timeout waiting for IRQ, err: %i\n", err);
170
if ((status&0xFFFF) != 0x101) printf("Invalid status %x\n", status);
174
// hpsleep(best_time);
178
} while (status != 0x101);
179
# else /* ADD_DELAYS */
182
} while (status != 0x101);
183
# endif /* ADD_DELAYS */
191
} while (status != 0);
192
#endif /* CHECK_READY */
196
gettimeofday(&end, NULL);
199
pcilib_kmem_sync_block(pci, kbuf, PCILIB_KMEM_SYNC_FROMDEVICE, 0);
201
for (i = 0; i < (HUGE_PAGE * PAGE_SIZE / 4); i++) {
202
// printf("%lx ", ptr0[i]);
203
if (ptr0[i] != 0x13131313) break;
205
if (i < (HUGE_PAGE * PAGE_SIZE / 4)) {
206
printf("Error in position %lu, value = %x\n", i * 4, ptr0[i]);
208
#endif /* CHECK_RESULT */
210
pcilib_free_kernel_memory(pci, kbuf, 0);
211
pcilib_disable_irq(pci, 0);
212
pcilib_unmap_bar(pci, BAR, bar);
215
run_time = (end.tv_sec - start.tv_sec) * 1000000 + (end.tv_usec - start.tv_usec);
216
size = (long long int)ITERATIONS * BUFFERS * HUGE_PAGE * PAGE_SIZE;
218
printf("%.3lf GB/s: transfered %zu bytes in %zu us using %u buffers\n", 1000000. * size / run_time / 1024 / 1024 / 1024, size, run_time, BUFFERS);
221
printf("Repeats: %lf, %lf\n",1. * rpt / (ITERATIONS * BUFFERS), 1. * rpt2 / (ITERATIONS * BUFFERS));