tiling_2d.c 6.27 KB
Newer Older
Swann Perarnau's avatar
Swann Perarnau committed
1 2 3 4 5 6 7 8 9 10
/*******************************************************************************
 * Copyright 2019 UChicago Argonne, LLC.
 * (c.f. AUTHORS, LICENSE)
 *
 * This file is part of the AML project.
 * For more info, see https://xgitlab.cels.anl.gov/argo/aml
 *
 * SPDX-License-Identifier: BSD-3-Clause
*******************************************************************************/

11
#include "aml.h"
12
#include "aml/tiling/2d.h"
13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60
#include <assert.h>

/*******************************************************************************
 * 2D Iterator
 ******************************************************************************/

int aml_tiling_iterator_2d_reset(struct aml_tiling_iterator_data *data)
{
	struct aml_tiling_iterator_2d_data *it =
		(struct aml_tiling_iterator_2d_data *)data;
	it->i = 0;
	return 0;
}

int aml_tiling_iterator_2d_end(const struct aml_tiling_iterator_data *data)
{
	const struct aml_tiling_iterator_2d_data *it =
		(const struct aml_tiling_iterator_2d_data *)data;
	return it->i * it->tiling->blocksize >= it->tiling->totalsize;
}

int aml_tiling_iterator_2d_next(struct aml_tiling_iterator_data *data)
{
	struct aml_tiling_iterator_2d_data *it =
		(struct aml_tiling_iterator_2d_data *)data;
	it->i++;
	return 0;
}

int aml_tiling_iterator_2d_get(const struct aml_tiling_iterator_data *data,
			       va_list args)
{
	const struct aml_tiling_iterator_2d_data *it =
		(const struct aml_tiling_iterator_2d_data *)data;
	unsigned long *x = va_arg(args, unsigned long *);
	*x = it->i;
	return 0;
}

struct aml_tiling_iterator_ops aml_tiling_iterator_2d_ops = {
	aml_tiling_iterator_2d_reset,
	aml_tiling_iterator_2d_next,
	aml_tiling_iterator_2d_end,
	aml_tiling_iterator_2d_get,
};

/*******************************************************************************
 * 2D ops
61
 * Tileids are the order in memory of the tiles.
62 63
 ******************************************************************************/

64
int aml_tiling_2d_rowmajor_tileid(const struct aml_tiling_data *t, va_list ap)
65 66 67
{
	const struct aml_tiling_2d_data *data =
		(const struct aml_tiling_2d_data *)t;
68 69
	size_t row = va_arg(ap, size_t);
	size_t col = va_arg(ap, size_t);
70 71

	if (row >= data->ndims[0] || col >= data->ndims[1])
72 73 74
		return -1;
	else
		return (row*data->ndims[1]) + col;
75 76
}

77
int aml_tiling_2d_colmajor_tileid(const struct aml_tiling_data *t, va_list ap)
78 79 80
{
	const struct aml_tiling_2d_data *data =
		(const struct aml_tiling_2d_data *)t;
81 82
	size_t row = va_arg(ap, size_t);
	size_t col = va_arg(ap, size_t);
83 84

	if (row >= data->ndims[0] || col >= data->ndims[1])
85
		return -1;
86
	else
87
		return (col*data->ndims[0]) + row;
88 89
}

90 91 92 93
size_t aml_tiling_2d_tilesize(const struct aml_tiling_data *t, int tileid)
{
	const struct aml_tiling_2d_data *data =
		(const struct aml_tiling_2d_data *)t;
94

95
	if (tileid < 0 || tileid >= (int)(data->ndims[0]*data->ndims[1]))
96 97 98 99 100
		return 0;
	else
		return data->blocksize;
}

101
void *aml_tiling_2d_tilestart(const struct aml_tiling_data *t,
102
			      const void *ptr, int tileid)
103 104 105 106
{
	const struct aml_tiling_2d_data *data =
		(const struct aml_tiling_2d_data *)t;
	intptr_t p = (intptr_t)ptr;
107

108
	if (tileid < 0 || tileid >= (int)(data->ndims[0]*data->ndims[1]))
109 110
		return NULL;
	else
111
		return (void *)(p + tileid*data->blocksize);
112 113 114 115 116 117
}

int aml_tiling_2d_ndims(const struct aml_tiling_data *t, va_list ap)
{
	const struct aml_tiling_2d_data *data =
		(const struct aml_tiling_2d_data *)t;
118 119
	size_t *nrows = va_arg(ap, size_t *);
	size_t *ncols = va_arg(ap, size_t *);
120

121
	/* looks totally wrong */
122 123
	*nrows = data->ndims[0];
	*ncols = data->ndims[1];
124 125 126
	return 0;
}

127
int aml_tiling_2d_create_iterator(struct aml_tiling_data *tiling,
128 129 130
				  struct aml_tiling_iterator **it, int flags)
{
	struct aml_tiling_iterator *ret;
131
	struct aml_tiling_iterator_2d_data *data;
Swann Perarnau's avatar
Swann Perarnau committed
132
	(void)flags;
133

Swann Perarnau's avatar
Swann Perarnau committed
134
	if (it == NULL)
135
		return -AML_EINVAL;
136

137
	*it = NULL;
138

139 140 141
	ret = calloc(1, sizeof(struct aml_tiling_iterator));
	if (ret == NULL)
		return -AML_ENOMEM;
142

143 144 145 146 147 148 149 150 151 152 153
	ret->ops = &aml_tiling_iterator_2d_ops;
	ret->data = calloc(1, sizeof(struct aml_tiling_iterator_2d_data));
	if (ret->data == NULL) {
		free(ret);
		return -AML_ENOMEM;
	}
	data = (struct aml_tiling_iterator_2d_data *)ret->data;
	data->i = 0;
	data->tiling = (struct aml_tiling_2d_data *)tiling;
	*it = ret;
	return AML_SUCCESS;
154 155
}

156
int aml_tiling_2d_destroy_iterator(struct aml_tiling_data *t,
157
				   struct aml_tiling_iterator **iter)
158
{
159
	struct aml_tiling_iterator *it;
160
	(void)t;
161 162 163 164 165 166 167 168 169 170

	if (iter == NULL)
		return -AML_EINVAL;
	it = *iter;
	if (it == NULL || it->data == NULL)
		return -AML_EINVAL;
	free(it->data);
	free(it);
	*iter = NULL;
	return AML_SUCCESS;
171
}
172

173 174 175
struct aml_tiling_ops aml_tiling_2d_rowmajor_ops = {
	aml_tiling_2d_create_iterator,
	aml_tiling_2d_destroy_iterator,
176
	aml_tiling_2d_rowmajor_tileid,
177
	aml_tiling_2d_tilesize,
178
	aml_tiling_2d_tilestart,
179 180 181 182
	aml_tiling_2d_ndims,
};

struct aml_tiling_ops aml_tiling_2d_colmajor_ops = {
183 184
	aml_tiling_2d_create_iterator,
	aml_tiling_2d_destroy_iterator,
185
	aml_tiling_2d_colmajor_tileid,
186
	aml_tiling_2d_tilesize,
187
	aml_tiling_2d_tilestart,
188
	aml_tiling_2d_ndims,
189
};
190 191 192 193 194

/*******************************************************************************
 * 2d create/destroy
 ******************************************************************************/

195
int aml_tiling_2d_create(struct aml_tiling **tiling, int type,
196 197 198 199
			 size_t tilesize, size_t totalsize,
			 size_t rowsize, size_t colsize)
{
	struct aml_tiling *ret = NULL;
200
	struct aml_tiling_2d_data *data;
201

202
	if (tiling == NULL)
203 204 205 206 207 208
		return -AML_EINVAL;

	if (type != AML_TILING_TYPE_2D_ROWMAJOR &&
	    type != AML_TILING_TYPE_2D_COLMAJOR)
		return -AML_EINVAL;

209 210 211 212 213
	if (tilesize > totalsize)
		return -AML_EINVAL;

	*tiling = NULL;

214
	/* alloc */
215
	ret = calloc(1, sizeof(struct aml_tiling));
Swann Perarnau's avatar
Swann Perarnau committed
216
	if (ret == NULL)
217 218 219 220 221 222 223
		return -AML_ENOMEM;

	if (type == AML_TILING_TYPE_2D_ROWMAJOR)
		ret->ops = &aml_tiling_2d_rowmajor_ops;
	else
		ret->ops = &aml_tiling_2d_colmajor_ops;

224 225
	ret->data = calloc(1, sizeof(struct aml_tiling_2d_data));
	if (ret->data == NULL) {
226
		free(ret);
227
		return -AML_ENOMEM;
228
	}
229
	data = (struct aml_tiling_2d_data *)ret->data;
230 231 232 233 234 235

	data->blocksize = tilesize;
	data->totalsize = totalsize;
	data->ndims[0] = rowsize;
	data->ndims[1] = colsize;

236 237
	*tiling = ret;
	return AML_SUCCESS;
238 239
}

240
void aml_tiling_2d_destroy(struct aml_tiling **tiling)
241
{
242 243 244 245 246 247
	struct aml_tiling *t;

	if (tiling == NULL)
		return;
	t = *tiling;
	if (t == NULL || t->data == NULL)
248
		return;
249 250 251
	free(t->data);
	free(t);
	*tiling = NULL;
252 253
}