signal.c 5.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207
  1. #include <stdio.h>
  2. #include <stdlib.h>
  3. #include <stdbool.h>
  4. #include <string.h>
  5. #include <pcilib.h>
  6. #include <pcilib/bar.h>
  7. #include <CL/cl.h>
  8. #include <CL/cl_ext.h>
  9. #include "ocl.h"
  10. /* this should actually come from the distributed pcitool sources */
  11. #include "pciDriver.h"
  12. typedef struct {
  13. /* pcilib */
  14. pcilib_t *pci;
  15. uint8_t *bar;
  16. cl_ulong bar_phys;
  17. /* OpenCL */
  18. OclPlatform *ocl;
  19. cl_device_id device;
  20. cl_command_queue queue;
  21. cl_context context;
  22. cl_program program;
  23. cl_kernel kernel;
  24. cl_mem fpga_buffer;
  25. cl_mem check_buffer;
  26. } App;
  27. #define WR32(addr, value) *(uint32_t *) (app->bar + (addr)) = (value);
  28. #define RD32(addr) (*(uint32_t *) (app->bar + (addr)))
  29. /* declaration should actually come from a distributed header file */
  30. const pcilib_board_info_t *pcilib_get_board_info (pcilib_t *);
  31. static bool
  32. init_pcilib (App *app)
  33. {
  34. static const char *DEVICE = "/dev/fpga0";
  35. const pcilib_board_info_t *board;
  36. app->pci = pcilib_open (DEVICE, "pci");
  37. if (app->pci == NULL) {
  38. printf ("Could not open `%s'", DEVICE);
  39. return false;
  40. }
  41. app->bar = pcilib_map_bar (app->pci, PCILIB_BAR0);
  42. if (app->bar == NULL) {
  43. printf ("Unable to map BAR\n");
  44. pcilib_close (app->pci);
  45. return false;
  46. }
  47. board = pcilib_get_board_info (app->pci);
  48. app->bar_phys = board->bar_start[PCILIB_BAR0];
  49. return true;
  50. }
  51. static void
  52. close_pcilib (App *app)
  53. {
  54. pcilib_unmap_bar (app->pci, PCILIB_BAR0, (void *) app->bar);
  55. pcilib_close (app->pci);
  56. }
  57. static cl_mem
  58. create_fpga_buffer (App *app, size_t size, cl_int *error)
  59. {
  60. cl_mem buffer;
  61. cl_mem_flags flags;
  62. cl_bus_address_amd addr;
  63. flags = CL_MEM_EXTERNAL_PHYSICAL_AMD;
  64. addr.surface_bus_address = (cl_ulong) app->bar_phys;
  65. addr.marker_bus_address = (cl_ulong) app->bar_phys;
  66. return clCreateBuffer (app->context, flags, size, &addr, error);
  67. }
  68. static bool
  69. init_opencl (App *app)
  70. {
  71. cl_int error;
  72. cl_platform_id platform;
  73. app->ocl = ocl_new_with_queues (0, CL_DEVICE_TYPE_GPU, 0);
  74. app->device = ocl_get_devices (app->ocl)[0];
  75. app->queue = ocl_get_cmd_queues (app->ocl)[0];
  76. app->context = ocl_get_context (app->ocl);
  77. app->program = ocl_create_program_from_file (app->ocl, "kernel.cl", NULL, &error);
  78. OCL_CHECK_ERROR (error);
  79. app->kernel = clCreateKernel (app->program, "write_to_fpga", &error);
  80. OCL_CHECK_ERROR (error);
  81. app->check_buffer = clCreateBuffer (app->context, CL_MEM_WRITE_ONLY, 8, NULL, &error);
  82. OCL_CHECK_ERROR (error);
  83. app->fpga_buffer = create_fpga_buffer (app, 1024 * 64, &error);
  84. OCL_CHECK_ERROR (error);
  85. return error != CL_SUCCESS ? false : true;
  86. }
  87. static void
  88. close_opencl (App *app)
  89. {
  90. OCL_CHECK_ERROR (clReleaseKernel (app->kernel));
  91. OCL_CHECK_ERROR (clReleaseProgram (app->program));
  92. OCL_CHECK_ERROR (clReleaseMemObject (app->fpga_buffer));
  93. OCL_CHECK_ERROR (clReleaseMemObject (app->check_buffer));
  94. ocl_free (app->ocl);
  95. }
  96. static void
  97. check_value (App *app, uint32_t addr, uint32_t expected)
  98. {
  99. uint32_t value;
  100. value = RD32 (addr);
  101. if (value != expected)
  102. printf ("failed [%u != %u]\n", value, expected);
  103. else
  104. printf ("success\n");
  105. }
  106. static void
  107. wait_on_and_release_event (cl_event event)
  108. {
  109. OCL_CHECK_ERROR (clWaitForEvents (1, &event));
  110. OCL_CHECK_ERROR (clReleaseEvent (event));
  111. }
  112. static void
  113. launch_signal (App *app)
  114. {
  115. cl_event event;
  116. uint32_t value;
  117. uintptr_t addr;
  118. uint32_t check[2];
  119. size_t global_work_size;
  120. addr = 0x9168;
  121. /* try to override defaultvalue */
  122. value = 0xc001;
  123. WR32 (addr, value);
  124. printf ("CPU WRITE ... ");
  125. check_value (app, addr, value);
  126. value = 0xdeadf00d;
  127. OCL_CHECK_ERROR (clSetKernelArg (app->kernel, 0, sizeof (cl_mem), &app->fpga_buffer));
  128. OCL_CHECK_ERROR (clSetKernelArg (app->kernel, 1, sizeof (cl_mem), &app->check_buffer));
  129. OCL_CHECK_ERROR (clSetKernelArg (app->kernel, 2, sizeof (uint32_t), &addr));
  130. OCL_CHECK_ERROR (clSetKernelArg (app->kernel, 3, sizeof (uint32_t), &value));
  131. global_work_size = 1;
  132. OCL_CHECK_ERROR (clEnqueueNDRangeKernel (app->queue, app->kernel, 1,
  133. NULL, &global_work_size, NULL,
  134. 0, NULL, &event));
  135. wait_on_and_release_event (event);
  136. /* let's see if the GPU wrote anything */
  137. printf ("GPU WRITE ... ");
  138. check_value (app, addr, value);
  139. /* let's see if the kernel did at least something */
  140. printf ("SANITY ...... ");
  141. check[0] = check[1] = 0;
  142. OCL_CHECK_ERROR (clEnqueueReadBuffer (app->queue, app->check_buffer, CL_TRUE, 0, 8, check, 0, NULL, NULL));
  143. if (check[0] == addr && check[1] == value)
  144. printf ("success\n");
  145. else
  146. printf ("failed [0x%x != 0x%x || 0x%x != 0x%x]\n", check[0], addr, check[1], value);
  147. }
  148. int
  149. main (int argc, char const* argv[])
  150. {
  151. App app;
  152. if (!init_pcilib (&app))
  153. return 1;
  154. if (!init_opencl (&app))
  155. return 1;
  156. launch_signal (&app);
  157. close_opencl (&app);
  158. close_pcilib (&app);
  159. return 0;
  160. }