/* Read context properties from a null-terminated sequence of * 'cl_context_properties' elements in guest memory */ void si_opencl_context_set_properties(struct si_opencl_context_t *context, struct mem_t *mem, unsigned int addr) { unsigned int property; unsigned int value; while (addr) { /* Read property */ mem_read(mem, addr, 4, &property); if (!property) break; mem_read(mem, addr + 4, 4, &value); addr += 8; /* Analyze property */ switch (property) { case 0x1084: /* CL_CONTEXT_PLATFORM */ context->platform_id = value; si_opencl_repo_get_object(si_emu->opencl_repo, si_opencl_object_platform, value); si_opencl_debug(" property CL_CONTEXT_PLATFORM assigned: 0x%x\n", value); break; default: fatal("opencl_context_read_properties: invalid property (0x%x)\n", property); } } }
int si_opencl_command_queue_can_wakeup(struct x86_ctx_t *ctx, void *data) { struct si_opencl_command_queue_t *command_queue; struct linked_list_t *command_list; int can_wakeup; /* x86 context can wakeup if command list is empty */ command_queue = data; command_list = command_queue->command_list; can_wakeup = !command_list->count; /* Debug */ if (can_wakeup) si_opencl_debug("\tcycle %lld - command queue 0x%x empty" " - context resumed\n", esim_cycle, command_queue->id); /* Return */ return can_wakeup; }
void si_ndrange_setup_args(struct si_ndrange_t *ndrange) { struct si_opencl_kernel_t *kernel = ndrange->kernel; struct si_opencl_kernel_arg_t *arg; int i; int j; int cb_index = 0; /* Kernel arguments */ for (i = 0; i < list_count(kernel->arg_list); i++) { arg = list_get(kernel->arg_list, i); assert(arg); /* Check that argument was set */ if (!arg->set) fatal("kernel '%s': argument '%s' has not been assigned with 'clKernelSetArg'.", kernel->name, arg->name); /* Process argument depending on its type */ switch (arg->kind) { case SI_OPENCL_KERNEL_ARG_KIND_VALUE: { /* Value copied directly into device constant memory */ for (j = 0; j < arg->size/4; j++) { si_isa_const_mem_write(1, (cb_index*4)*4+j, &arg->data.value[j]); si_opencl_debug(" arg %d: value '0x%x' loaded into " "CB1[%d][%d]\n", i, arg->data.value[j], cb_index, j); } cb_index++; break; } case SI_OPENCL_KERNEL_ARG_KIND_POINTER: { switch (arg->mem_scope) { case SI_OPENCL_MEM_SCOPE_CONSTANT: case SI_OPENCL_MEM_SCOPE_GLOBAL: { struct si_opencl_mem_t *mem; /* Pointer in __global scope. * Argument value is a pointer to an 'opencl_mem' object. * It is translated first into a device memory pointer. */ mem = si_opencl_repo_get_object(si_emu->opencl_repo, si_opencl_object_mem, arg->data.ptr); si_isa_const_mem_write(1, (cb_index*4)*4, &mem->device_ptr); si_opencl_debug(" arg %d: opencl_mem id 0x%x loaded into CB1[%d]," " device_ptr=0x%x\n", i, arg->data.ptr, cb_index, mem->device_ptr); cb_index++; break; } case SI_OPENCL_MEM_SCOPE_LOCAL: { /* Pointer in __local scope. * Argument value is always NULL, just assign space for it. */ si_isa_const_mem_write(1, (cb_index*4)*4, &ndrange->local_mem_top); si_opencl_debug(" arg %d: %d bytes reserved in local memory at 0x%x\n", i, arg->size, ndrange->local_mem_top); ndrange->local_mem_top += arg->size; cb_index++; break; } default: { fatal("%s: argument in memory scope %d not supported", __FUNCTION__, arg->mem_scope); } } break; } default: { fatal("%s: argument type not reconized", __FUNCTION__); } } } }
static void si_opencl_kernel_load_metadata(struct si_opencl_kernel_t *kernel) { char line[MAX_STRING_SIZE]; char *line_ptrs[MAX_STRING_SIZE]; int token_count; struct si_opencl_kernel_arg_t *arg; struct elf_buffer_t *buffer; /* Open as text file */ buffer = &kernel->metadata_buffer; elf_buffer_seek(buffer, 0); si_opencl_debug("Kernel Metadata:\n"); for (;;) { /* Read line from buffer */ elf_buffer_read_line(buffer, line, MAX_STRING_SIZE); if (!line[0]) break; si_opencl_debug("\t%s\n", line); /* Split line */ line_ptrs[0] = strtok(line, ":;\n"); for (token_count = 1; (line_ptrs[token_count] = strtok(NULL, ":\n")); token_count++); /* Ignored entries */ if (!line_ptrs[0] || !strcmp(line_ptrs[0], "ARGSTART") || !strcmp(line_ptrs[0], "version") || !strcmp(line_ptrs[0], "device") || !strcmp(line_ptrs[0], "uniqueid") || !strcmp(line_ptrs[0], "uavid") || !strcmp(line_ptrs[0], "privateid") || !strcmp(line_ptrs[0], "reflection") || !strcmp(line_ptrs[0], "ARGEND")) continue; /* Image */ if (!strcmp(line_ptrs[0], "image")) { /* Create input image argument */ arg = si_opencl_kernel_arg_create(line_ptrs[1]); arg->kind = SI_OPENCL_KERNEL_ARG_KIND_IMAGE; if (!strcmp(line_ptrs[2], "2D")) { /* Ignore dimensions for now */ } else if (!strcmp(line_ptrs[2], "3D")) { /* Ignore dimensions for now */ } else { fatal("%s: Invalid number of dimensions for OpenCL Image (%s)\n%s", __FUNCTION__, line_ptrs[2], si_err_opencl_param_note); } if (!strcmp(line_ptrs[3], "RO")) { arg->access_type = SI_OPENCL_KERNEL_ARG_READ_ONLY; } else if (!strcmp(line_ptrs[3], "WO")) { arg->access_type = SI_OPENCL_KERNEL_ARG_WRITE_ONLY; } else { fatal("%s: Invalid memory access type for OpenCL Image (%s)\n%s", __FUNCTION__, line_ptrs[3], si_err_opencl_param_note); } arg->uav = atoi(line_ptrs[4]); arg->mem_scope = SI_OPENCL_MEM_SCOPE_GLOBAL; list_add(kernel->arg_list, arg); continue; } /* Memory */ if (!strcmp(line_ptrs[0], "memory")) { if (!strcmp(line_ptrs[1], "hwprivate")) { SI_OPENCL_KERNEL_METADATA_NOT_SUPPORTED_NEQ(2, "0"); } else if (!strcmp(line_ptrs[1], "hwregion")) { SI_OPENCL_KERNEL_METADATA_TOKEN_COUNT(3); SI_OPENCL_KERNEL_METADATA_NOT_SUPPORTED_NEQ(2, "0"); } else if (!strcmp(line_ptrs[1], "hwlocal")) { SI_OPENCL_KERNEL_METADATA_TOKEN_COUNT(3); kernel->func_mem_local = atoi(line_ptrs[2]); } else if (!strcmp(line_ptrs[1], "datareqd")) { SI_OPENCL_KERNEL_METADATA_TOKEN_COUNT(2); } else if (!strcmp(line_ptrs[1], "uavprivate")) { SI_OPENCL_KERNEL_METADATA_TOKEN_COUNT(3); } else SI_OPENCL_KERNEL_METADATA_NOT_SUPPORTED(1); continue; } /* Entry 'value'. Format: value:<ArgName>:<DataType>:<Size>:<ConstNum>:<ConstOffset> */ if (!strcmp(line_ptrs[0], "value")) { SI_OPENCL_KERNEL_METADATA_TOKEN_COUNT(6); //SI_OPENCL_KERNEL_METADATA_NOT_SUPPORTED_NEQ(3, "1"); SI_OPENCL_KERNEL_METADATA_NOT_SUPPORTED_NEQ(4, "1"); arg = si_opencl_kernel_arg_create(line_ptrs[1]); arg->kind = SI_OPENCL_KERNEL_ARG_KIND_VALUE; list_add(kernel->arg_list, arg); continue; } /* Entry 'pointer'. Format: pointer:<name>:<type>:?:?:<addr>:?:?:<elem_size> */ if (!strcmp(line_ptrs[0], "pointer")) { /* APP SDK 2.5 supplies 9 tokens, 2.6 supplies 10 tokens */ /* Metadata version 3:1:104 (as specified in entry 'version') uses 12 items. */ if (token_count != 9 && token_count != 10 && token_count != 12) { SI_OPENCL_KERNEL_METADATA_TOKEN_COUNT(10); } SI_OPENCL_KERNEL_METADATA_NOT_SUPPORTED_NEQ(3, "1"); SI_OPENCL_KERNEL_METADATA_NOT_SUPPORTED_NEQ(4, "1"); /* We don't know what the two last entries are, so make sure that they are * set to 0. If they're not 0, it probably means something important. */ if (token_count == 12) { SI_OPENCL_KERNEL_METADATA_NOT_SUPPORTED_NEQ(10, "0"); SI_OPENCL_KERNEL_METADATA_NOT_SUPPORTED_NEQ(11, "0"); } arg = si_opencl_kernel_arg_create(line_ptrs[1]); arg->kind = SI_OPENCL_KERNEL_ARG_KIND_POINTER; list_add(kernel->arg_list, arg); if (!strcmp(line_ptrs[6], "uav")) { arg->mem_scope = SI_OPENCL_MEM_SCOPE_GLOBAL; arg->uav = atoi(line_ptrs[7]); } else if (!strcmp(line_ptrs[6], "hl")) { arg->mem_scope = SI_OPENCL_MEM_SCOPE_LOCAL; arg->uav = atoi(line_ptrs[7]); } else if (!strcmp(line_ptrs[6], "hc")) { arg->mem_scope = SI_OPENCL_MEM_SCOPE_CONSTANT; arg->uav = atoi(line_ptrs[7]); } else SI_OPENCL_KERNEL_METADATA_NOT_SUPPORTED(6); continue; } /* Entry 'function'. Format: function:?:<uniqueid> */ if (!strcmp(line_ptrs[0], "function")) { SI_OPENCL_KERNEL_METADATA_TOKEN_COUNT(3); SI_OPENCL_KERNEL_METADATA_NOT_SUPPORTED_NEQ(1, "1"); kernel->func_uniqueid = atoi(line_ptrs[2]); continue; } /* Entry 'sampler'. Format: sampler:name:ID:location:value. * 'location' is 1 for kernel defined samplers, 0 for kernel argument. * 'value' is bitfield value of sampler (0 if a kernel argument) */ if (!strcmp(line_ptrs[0], "sampler")) { /* As far as I can tell, the actual sampler data is stored * as a value, so adding it to the argument list is not required */ continue; } /* Entry 'reflection'. Format: reflection:<arg_id>:<type> * Observed first in version 3:1:104 of metadata. * This entry specifies the type of the argument, as specified in the OpenCL * kernel function header. It is currently ignored, since this information * is extracted from the argument descriptions in 'value' and 'pointer' entries. */ if (!strcmp(line_ptrs[0], "reflection")) { SI_OPENCL_KERNEL_METADATA_TOKEN_COUNT(3); continue; } /* Entry 'privateid'. Format: privateid:<id> * Observed first in version 3:1:104 of metadata. Not sure what this entry is for. */ if (!strcmp(line_ptrs[0], "privateid")) { SI_OPENCL_KERNEL_METADATA_TOKEN_COUNT(2); continue; } /* Entry 'constarg'. Format: constarg:<arg_id>:<arg_name> * Observed first in version 3:1:104 of metadata. It shows up when an argument * is declared as '__global const'. Entry ignored here. */ if (!strcmp(line_ptrs[0], "constarg")) { SI_OPENCL_KERNEL_METADATA_TOKEN_COUNT(3); continue; } /* Warn about uninterpreted entries */ warning("kernel '%s': unknown meta data entry '%s'", kernel->name, line_ptrs[0]); } }