Commit a13ddad2 authored by Brian Suchy's avatar Brian Suchy Committed by Swann Perarnau
Browse files

[feature] add 2D tiling, additional methods.

Implement a 2D tiling with continuous tiles in memory, with tiles
organized in row-major order inside the virtual address range.

Also adds functions to query the size of a tile inside the tiling.
parent c1ec7da8
......@@ -10,7 +10,7 @@ AREA_LINUX_CSOURCES = area_linux.c \
AREA_POSIX_CSOURCES = area_posix.c
TILING_CSOURCES = tiling.c tiling_1d.c
TILING_CSOURCES = tiling.c tiling_1d.c tiling_2d.c
BINDING_CSOURCES = binding.c \
binding_single.c \
......
......@@ -769,6 +769,8 @@ struct aml_tiling_ops {
int (*destroy_iterator)(struct aml_tiling_data *tiling,
struct aml_tiling_iterator *iterator);
size_t (*tilesize)(const struct aml_tiling_data *tiling, int tileid);
size_t (*tilerowsize)(const struct aml_tiling_data *tiling, int tileid);
size_t (*tilecolsize)(const struct aml_tiling_data *tiling, int tileid);
void* (*tilestart)(const struct aml_tiling_data *tiling,
const void *ptr, int tileid);
};
......@@ -786,6 +788,25 @@ struct aml_tiling {
* Returns the size of a tile.
*/
size_t aml_tiling_tilesize(const struct aml_tiling *tiling, int tileid);
/*
* Provides the information on the size of a tile row.
* "tiling": an initialized tiling structure.
* "tileid": an identifier of a tile (a value between 0 and the number of tiles
* minus 1).
* Returns the size of a tile row.
*/
size_t aml_tiling_tilerowsize(const struct aml_tiling *tiling, int tileid);
/*
* Provides the information on the size of a tile column.
* "tiling": an initialized tiling structure.
* "tileid": an identifier of a tile (a value between 0 and the number of tiles
* minus 1).
* Returns the size of a tile col.
*/
size_t aml_tiling_tilecolsize(const struct aml_tiling *tiling, int tileid);
/*
* Provides the information on the location of a tile in memory.
* "tiling": an initialized tiling structure.
......@@ -873,6 +894,7 @@ int aml_tiling_iterator_get(const struct aml_tiling_iterator *iterator, ...);
/* Tiling types passed to the tiling create()/init()/vinit() routines. */
/* Regular, linear tiling with uniform tile sizes. */
#define AML_TILING_TYPE_1D 0
#define AML_TILING_TYPE_2D 2
/*
* Allocates and initializes a new tiling.
......@@ -950,6 +972,46 @@ struct aml_tiling_iterator_1d_data {
(sizeof(struct aml_tiling_iterator_1d_data) + \
sizeof(struct aml_tiling_iterator))
/*******************************************************************************
* Tiling 2D:
******************************************************************************/
extern struct aml_tiling_ops aml_tiling_2d_ops;
extern struct aml_tiling_iterator_ops aml_tiling_iterator_2d_ops;
struct aml_tiling_2d_data {
size_t blocksize;
size_t tilerowsize;
size_t tilecolsize;
size_t totalsize;
};
struct aml_tiling_iterator_2d_data {
size_t i;
struct aml_tiling_2d_data *tiling;
};
#define AML_TILING_2D_DECL(name) \
struct aml_tiling_2d_data __ ##name## _inner_data; \
struct aml_tiling name = { \
&aml_tiling_2d_ops, \
(struct aml_tiling_data *)&__ ## name ## _inner_data, \
};
#define AML_TILING_ITERATOR_2D_DECL(name) \
struct aml_tiling_iterator_2d_data __ ##name## _inner_data; \
struct aml_tiling_iterator name = { \
&aml_tiling_iterator_2d_ops, \
(struct aml_tiling_iterator_data *)&__ ## name ## _inner_data, \
};
#define AML_TILING_2D_ALLOCSIZE (sizeof(struct aml_tiling_2d_data) + \
sizeof(struct aml_tiling))
#define AML_TILING_ITERATOR_2D_ALLOCSIZE \
(sizeof(struct aml_tiling_iterator_2d_data) + \
sizeof(struct aml_tiling_iterator))
/*******************************************************************************
* Binding:
* Representation of page bindings in an area
......
......@@ -10,6 +10,18 @@ size_t aml_tiling_tilesize(const struct aml_tiling *t, int tileid)
return t->ops->tilesize(t->data, tileid);
}
size_t aml_tiling_tilerowsize(const struct aml_tiling *t, int tileid)
{
assert(t != NULL);
return t->ops->tilerowsize(t->data, tileid);
}
size_t aml_tiling_tilecolsize(const struct aml_tiling *t, int tileid)
{
assert(t != NULL);
return t->ops->tilecolsize(t->data, tileid);
}
void* aml_tiling_tilestart(const struct aml_tiling *t, const void *ptr, int tileid)
{
assert(t != NULL);
......@@ -83,9 +95,14 @@ int aml_tiling_destroy_iterator(struct aml_tiling *t,
******************************************************************************/
/* allocate and init the tiling according to type */
//In the future, a n-dimensional arrya could be created with an arguments of:
//type: n # of dimensions
//va_list: size of each dimension followed by total size
//The return is now changed to ensure that a tile size is not larger than the given total size
int aml_tiling_create(struct aml_tiling **t, int type, ...)
{
va_list ap;
int err;
va_start(ap, type);
struct aml_tiling *ret = NULL;
intptr_t baseptr, dataptr;
......@@ -93,29 +110,59 @@ int aml_tiling_create(struct aml_tiling **t, int type, ...)
{
/* alloc */
baseptr = (intptr_t) calloc(1, AML_TILING_1D_ALLOCSIZE);
dataptr = baseptr + sizeof(struct aml_tiling);
dataptr = baseptr + sizeof(struct aml_tiling);
ret = (struct aml_tiling *)baseptr;
ret->data = (struct aml_tiling_data *)dataptr;
aml_tiling_vinit(ret, type, ap);
err = aml_tiling_vinit(ret, type, ap);
}
else if(type == AML_TILING_TYPE_2D)
{
/* alloc, only difference is using AML_TILING_2D_ALLOCSIZE instead fo 1D */
baseptr = (intptr_t) calloc(1, AML_TILING_2D_ALLOCSIZE);
dataptr = baseptr + sizeof(struct aml_tiling);
ret = (struct aml_tiling *)baseptr;
ret->data = (struct aml_tiling_data *)dataptr;
err = aml_tiling_vinit(ret, type, ap);
}
va_end(ap);
*t = ret;
return 0;
return err;
}
int aml_tiling_vinit(struct aml_tiling *t, int type, va_list ap)
{
int err;
if(type == AML_TILING_TYPE_1D)
{
t->ops = &aml_tiling_1d_ops;
struct aml_tiling_1d_data *data =
struct aml_tiling_1d_data *data =
(struct aml_tiling_1d_data *)t->data;
data->blocksize = va_arg(ap, size_t);
data->totalsize = va_arg(ap, size_t);
err = data->blocksize > data->totalsize;
}
return 0;
//This is equivalent to the 1D except the arguments will be the dimensions for the tile.
//An optimization that could be made is having the exact same declaration of 1D
//The caveat is that the block size must be a perfect square. For now, we will allow non-square blocks
else if(type == AML_TILING_TYPE_2D)
{
t->ops = &aml_tiling_2d_ops;
struct aml_tiling_2d_data *data =
(struct aml_tiling_2d_data *)t->data;
data->tilerowsize = va_arg(ap, size_t);
data->tilecolsize = va_arg(ap, size_t);
data->blocksize = data->tilerowsize * data->tilecolsize / sizeof(unsigned long);
data->totalsize = va_arg(ap, size_t);
err = data->blocksize > data->totalsize;
}
return err;
}
int aml_tiling_init(struct aml_tiling *t, int type, ...)
......
......@@ -56,6 +56,21 @@ size_t aml_tiling_1d_tilesize(const struct aml_tiling_data *t, int tileid)
return data->blocksize;
}
//A 1-D array is technically just a multidimensional array with all dimensions except the row size equal to 1
//See aml_tiling_1d_colsize to understand.
size_t aml_tiling_1d_tilerowsize(const struct aml_tiling_data *t, int tileid)
{
const struct aml_tiling_1d_data *data =
(const struct aml_tiling_1d_data *)t;
return data->blocksize;
}
size_t aml_tiling_1d_tilecolsize(const struct aml_tiling_data *t, int tileid)
{
return 8;
}
void* aml_tiling_1d_tilestart(const struct aml_tiling_data *t, const void *ptr, int tileid)
{
const struct aml_tiling_1d_data *data =
......@@ -103,5 +118,7 @@ struct aml_tiling_ops aml_tiling_1d_ops = {
aml_tiling_1d_init_iterator,
aml_tiling_1d_destroy_iterator,
aml_tiling_1d_tilesize,
aml_tiling_1d_tilerowsize,
aml_tiling_1d_tilecolsize,
aml_tiling_1d_tilestart,
};
#include <aml.h>
#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
******************************************************************************/
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;
return data->blocksize;
}
size_t aml_tiling_2d_tilerowsize(const struct aml_tiling_data *t, int tileid)
{
const struct aml_tiling_2d_data *data =
(const struct aml_tiling_2d_data *)t;
return data->tilerowsize;
}
size_t aml_tiling_2d_tilecolsize(const struct aml_tiling_data *t, int tileid)
{
const struct aml_tiling_2d_data *data =
(const struct aml_tiling_2d_data *)t;
return data->tilecolsize;
}
void* aml_tiling_2d_tilestart(const struct aml_tiling_data *t, const void *ptr, int tileid)
{
const struct aml_tiling_2d_data *data =
(const struct aml_tiling_2d_data *)t;
intptr_t p = (intptr_t)ptr;
return (void *)(p + tileid*data->blocksize);
}
int aml_tiling_2d_init_iterator(struct aml_tiling_data *t,
struct aml_tiling_iterator *it, int flags)
{
assert(it->data != NULL);
struct aml_tiling_iterator_1d_data *data =
(struct aml_tiling_iterator_2d_data *)it->data;
it->ops = &aml_tiling_iterator_2d_ops;
data->i = 0;
data->tiling = (struct aml_tiling_2d_data *)t;
return 0;
}
int aml_tiling_2d_create_iterator(struct aml_tiling_data *t,
struct aml_tiling_iterator **it, int flags)
{
intptr_t baseptr, dataptr;
struct aml_tiling_iterator *ret;
baseptr = (intptr_t) calloc(1, AML_TILING_ITERATOR_2D_ALLOCSIZE);
dataptr = baseptr + sizeof(struct aml_tiling_iterator);
ret = (struct aml_tiling_iterator *)baseptr;
ret->data = (struct aml_tiling_iterator_data *)dataptr;
aml_tiling_2d_init_iterator(t, ret, flags);
*it = ret;
return 0;
}
int aml_tiling_2d_destroy_iterator(struct aml_tiling_data *t,
struct aml_tiling_iterator *it)
{
return 0;
}
struct aml_tiling_ops aml_tiling_2d_ops = {
aml_tiling_2d_create_iterator,
aml_tiling_2d_init_iterator,
aml_tiling_2d_destroy_iterator,
aml_tiling_2d_tilesize,
aml_tiling_2d_tilerowsize,
aml_tiling_2d_tilecolsize,
aml_tiling_2d_tilestart,
};
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment