00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00029 #include "cell_context.h"
00030 #include "cell_batch.h"
00031 #include "cell_spu.h"
00032
00033
00034
00042 uint
00043 cell_get_empty_buffer(struct cell_context *cell)
00044 {
00045 uint buf = 0, tries = 0;
00046
00047
00048 while (1) {
00049 uint spu, num_free = 0;
00050
00051 for (spu = 0; spu < cell->num_spus; spu++) {
00052 if (cell->buffer_status[spu][buf][0] == CELL_BUFFER_STATUS_FREE) {
00053 num_free++;
00054
00055 if (num_free == cell->num_spus) {
00056
00057 for (spu = 0; spu < cell->num_spus; spu++) {
00058 cell->buffer_status[spu][buf][0] = CELL_BUFFER_STATUS_USED;
00059 }
00060
00061
00062
00063 return buf;
00064 }
00065 }
00066 else {
00067 break;
00068 }
00069 }
00070
00071
00072 buf = (buf + 1) % CELL_NUM_BUFFERS;
00073
00074 tries++;
00075 if (tries == 100) {
00076
00077
00078
00079 }
00080 }
00081 }
00082
00083
00089 void
00090 cell_batch_flush(struct cell_context *cell)
00091 {
00092 static boolean flushing = FALSE;
00093 uint batch = cell->cur_batch;
00094 const uint size = cell->buffer_size[batch];
00095 uint spu, cmd_word;
00096
00097 assert(!flushing);
00098
00099 if (size == 0)
00100 return;
00101
00102 flushing = TRUE;
00103
00104 assert(batch < CELL_NUM_BUFFERS);
00105
00106
00107
00108
00109
00110
00111
00112
00113
00114 cmd_word = CELL_CMD_BATCH | (batch << 8) | (size << 16);
00115
00116 for (spu = 0; spu < cell->num_spus; spu++) {
00117 assert(cell->buffer_status[spu][batch][0] == CELL_BUFFER_STATUS_USED);
00118 send_mbox_message(cell_global.spe_contexts[spu], cmd_word);
00119 }
00120
00121
00122
00123
00124
00125
00126 batch = cell_get_empty_buffer(cell);
00127
00128 cell->buffer_size[batch] = 0;
00129 cell->cur_batch = batch;
00130
00131 flushing = FALSE;
00132 }
00133
00134
00138 uint
00139 cell_batch_free_space(const struct cell_context *cell)
00140 {
00141 uint free = CELL_BUFFER_SIZE - cell->buffer_size[cell->cur_batch];
00142 return free;
00143 }
00144
00145
00151 void
00152 cell_batch_append(struct cell_context *cell, const void *data, uint bytes)
00153 {
00154 uint size;
00155
00156 ASSERT(bytes % 8 == 0);
00157 ASSERT(bytes <= CELL_BUFFER_SIZE);
00158 ASSERT(cell->cur_batch >= 0);
00159
00160 #ifdef ASSERT
00161 {
00162 uint spu;
00163 for (spu = 0; spu < cell->num_spus; spu++) {
00164 ASSERT(cell->buffer_status[spu][cell->cur_batch][0]
00165 == CELL_BUFFER_STATUS_USED);
00166 }
00167 }
00168 #endif
00169
00170 size = cell->buffer_size[cell->cur_batch];
00171
00172 if (size + bytes > CELL_BUFFER_SIZE) {
00173 cell_batch_flush(cell);
00174 size = 0;
00175 }
00176
00177 ASSERT(size + bytes <= CELL_BUFFER_SIZE);
00178
00179 memcpy(cell->buffer[cell->cur_batch] + size, data, bytes);
00180
00181 cell->buffer_size[cell->cur_batch] = size + bytes;
00182 }
00183
00184
00189 void *
00190 cell_batch_alloc(struct cell_context *cell, uint bytes)
00191 {
00192 return cell_batch_alloc_aligned(cell, bytes, 1);
00193 }
00194
00195
00200 void *
00201 cell_batch_alloc_aligned(struct cell_context *cell, uint bytes,
00202 uint alignment)
00203 {
00204 void *pos;
00205 uint size, padbytes;
00206
00207 ASSERT(bytes % 8 == 0);
00208 ASSERT(bytes <= CELL_BUFFER_SIZE);
00209 ASSERT(alignment > 0);
00210 ASSERT(cell->cur_batch >= 0);
00211
00212 #ifdef ASSERT
00213 {
00214 uint spu;
00215 for (spu = 0; spu < cell->num_spus; spu++) {
00216 ASSERT(cell->buffer_status[spu][cell->cur_batch][0]
00217 == CELL_BUFFER_STATUS_USED);
00218 }
00219 }
00220 #endif
00221
00222 size = cell->buffer_size[cell->cur_batch];
00223
00224 padbytes = (alignment - (size % alignment)) % alignment;
00225
00226 if (padbytes + size + bytes > CELL_BUFFER_SIZE) {
00227 cell_batch_flush(cell);
00228 size = 0;
00229 }
00230 else {
00231 size += padbytes;
00232 }
00233
00234 ASSERT(size % alignment == 0);
00235 ASSERT(size + bytes <= CELL_BUFFER_SIZE);
00236
00237 pos = (void *) (cell->buffer[cell->cur_batch] + size);
00238
00239 cell->buffer_size[cell->cur_batch] = size + bytes;
00240
00241 return pos;
00242 }
00243
00244
00248 void
00249 cell_init_batch_buffers(struct cell_context *cell)
00250 {
00251 uint spu, buf;
00252
00253
00254 for (buf = 0; buf < CELL_NUM_BUFFERS; buf++) {
00255 cell->buffer_size[buf] = 0;
00256
00257
00258
00259
00260 for (spu = 0; spu < cell->num_spus; spu++) {
00261 if (buf == 0)
00262 cell->buffer_status[spu][buf][0] = CELL_BUFFER_STATUS_USED;
00263 else
00264 cell->buffer_status[spu][buf][0] = CELL_BUFFER_STATUS_FREE;
00265 }
00266 }
00267 }