void evg_ndrange_free(struct evg_ndrange_t *ndrange)
{
	int i;

	/* Clear task from command queue */
	if (ndrange->command_queue && ndrange->command)
	{
		evg_opencl_command_queue_complete(ndrange->command_queue, ndrange->command);
		evg_opencl_command_free(ndrange->command);
	}

	/* Clear all states that affect lists. */
	evg_ndrange_clear_status(ndrange, evg_ndrange_pending);
	evg_ndrange_clear_status(ndrange, evg_ndrange_running);
	evg_ndrange_clear_status(ndrange, evg_ndrange_finished);

	/* Extract from ND-Range list in Evergreen emulator */
	assert(DOUBLE_LINKED_LIST_MEMBER(evg_emu, ndrange, ndrange));
	DOUBLE_LINKED_LIST_REMOVE(evg_emu, ndrange, ndrange);

	/* Free work-groups */
	for (i = 0; i < ndrange->work_group_count; i++)
		evg_work_group_free(ndrange->work_groups[i]);
	free(ndrange->work_groups);

	/* Free wavefronts */
	for (i = 0; i < ndrange->wavefront_count; i++)
		evg_wavefront_free(ndrange->wavefronts[i]);
	free(ndrange->wavefronts);

	/* Free work-items */
	for (i = 0; i < ndrange->work_item_count; i++)
		evg_work_item_free(ndrange->work_items[i]);
	free(ndrange->work_items);

	/* Free instruction histogram */
	if (ndrange->inst_histogram)
		free(ndrange->inst_histogram);

	/* Free ND-Range */
	free(ndrange->name);
	free(ndrange);
}
Exemple #2
0
int EvgGpuRun(Timing *self)
{
	EvgGpu *gpu = asEvgGpu(self);

	struct evg_ndrange_t *ndrange;

	struct evg_compute_unit_t *compute_unit;
	struct evg_compute_unit_t *compute_unit_next;

	/* For efficiency when no Evergreen emulation is selected, exit here
	 * if the list of existing ND-Ranges is empty. */
	if (!evg_emu->ndrange_list_count)
		return FALSE;

	/* Start one ND-Range in state 'pending' */
	while ((ndrange = evg_emu->pending_ndrange_list_head))
	{
		/* Currently not supported for more than 1 ND-Range */
		if (gpu->ndrange)
			fatal("%s: Evergreen GPU timing simulation not supported for multiple ND-Ranges",
				__FUNCTION__);

		/* Set ND-Range status to 'running' */
		evg_ndrange_clear_status(ndrange, evg_ndrange_pending);
		evg_ndrange_set_status(ndrange, evg_ndrange_running);

		/* Trace */
		evg_trace("evg.new_ndrange "
			"id=%d "
			"wg_first=%d "
			"wg_count=%d\n",
			ndrange->id,
			ndrange->work_group_id_first,
			ndrange->work_group_count);

		/* Map ND-Range to GPU */
		evg_gpu_map_ndrange(ndrange);
		evg_calc_plot();
	}

	/* Mapped ND-Range */
	ndrange = gpu->ndrange;
	assert(ndrange);

	/* Allocate work-groups to compute units */
	while (gpu->ready_list_head && ndrange->pending_list_head)
		evg_compute_unit_map_work_group(gpu->ready_list_head,
			ndrange->pending_list_head);

	/* One more cycle */
	asTiming(evg_gpu)->cycle++;

	/* Stop if maximum number of GPU cycles exceeded */
	if (evg_emu_max_cycles && asTiming(evg_gpu)->cycle >= evg_emu_max_cycles)
		esim_finish = esim_finish_evg_max_cycles;

	/* Stop if maximum number of GPU instructions exceeded */
	if (evg_emu_max_inst && asEmu(evg_emu)->instructions >= evg_emu_max_inst)
		esim_finish = esim_finish_evg_max_inst;
	
	/* Stop if there was a simulation stall */
	if (asTiming(evg_gpu)->cycle - gpu->last_complete_cycle > 1000000)
	{
		warning("Evergreen GPU simulation stalled.\n%s",
			evg_err_stall);
		esim_finish = esim_finish_stall;
	}

	/* Stop if any reason met */
	if (esim_finish)
		return TRUE;

	/* Free instructions in trash */
	evg_gpu_uop_trash_empty();

	/* Run one loop iteration on each busy compute unit */
	for (compute_unit = gpu->busy_list_head; compute_unit;
		compute_unit = compute_unit_next)
	{
		/* Store next busy compute unit, since this can change
		 * during the compute unit simulation loop iteration. */
		compute_unit_next = compute_unit->busy_list_next;

		/* Run one cycle */
		evg_compute_unit_run(compute_unit);
	}

	/* GPU-REL: insert stack faults */
	evg_faults_insert();

	/* If ND-Range finished execution in all compute units, free it. */
	if (!gpu->busy_list_count)
	{
		/* Dump ND-Range report */
		evg_ndrange_dump(ndrange, evg_emu_report_file);

		/* Stop if maximum number of kernels reached */
		if (evg_emu_max_kernels && evg_emu->ndrange_count >= evg_emu_max_kernels)
			esim_finish = esim_finish_evg_max_kernels;

		/* Finalize and free ND-Range */
		assert(evg_ndrange_get_status(ndrange, evg_ndrange_finished));
		evg_gpu_uop_trash_empty();
		evg_gpu_unmap_ndrange();
		evg_ndrange_free(ndrange);
	}

	/* Still simulating */
	return TRUE;
}