void ebsp_create_down_stream(const void* src, int dst_core_id, int nbytes, int max_chunksize) { if (max_chunksize < MINIMUM_CHUNK_SIZE) { printf("ERROR: minimum chunk size is %i bytes\n", MINIMUM_CHUNK_SIZE); return; } int nchunks = (nbytes + max_chunksize - 1) / max_chunksize; // nbytes/chunksize rounded up int nbytes_including_headers = nbytes + nchunks * 2 * sizeof(int) + 2 * sizeof(int); // the +2*sizeof(int) is the terminating header // headers consist of 2 ints: prev size and next size // 1) malloc in extmem void* extmem_in_buffer = ebsp_ext_malloc(nbytes_including_headers); if (extmem_in_buffer == 0) { printf( "ERROR: not enough memory in extmem for ebsp_send_buffered_raw\n"); return; } // 2) copy the data to extmem, inserting headers unsigned dst_cursor = (unsigned)extmem_in_buffer; unsigned src_cursor = (unsigned)src; int current_chunksize = max_chunksize; int last_chunksize = 0; for (int nbytes_left = nbytes; nbytes_left > 0; nbytes_left -= max_chunksize) { if (nbytes_left < max_chunksize) current_chunksize = nbytes_left; (*(int*)dst_cursor) = last_chunksize; // write prev header dst_cursor += sizeof(int); (*(int*)dst_cursor) = current_chunksize; // write next header dst_cursor += sizeof(int); memcpy((void*)dst_cursor, (void*)src_cursor, current_chunksize); dst_cursor += current_chunksize; src_cursor += current_chunksize; last_chunksize = current_chunksize; } (*(int*)dst_cursor) = current_chunksize; // write terminating header (prev) dst_cursor += sizeof(int); (*(int*)dst_cursor) = 0; // write terminating header (next) dst_cursor += sizeof(int); // 3) add stream to state _ebsp_add_stream(dst_core_id, extmem_in_buffer, nbytes_including_headers, max_chunksize, 1); }
void ebsp_create_down_stream_raw(const void* src, int dst_core_id, int nbytes, int max_chunksize) { // 1) malloc in extmem void* extmem_in_buffer = ebsp_ext_malloc(nbytes); if (extmem_in_buffer == 0) { printf( "ERROR: not enough memory in extmem for ebsp_send_buffered_raw\n"); return; } // 2) copy the data there directly memcpy(extmem_in_buffer, src, nbytes); // 3) add stream to state _ebsp_add_stream(dst_core_id, extmem_in_buffer, nbytes, max_chunksize, 1); }
void* ebsp_create_up_stream(int src_core_id, int nbytes, int max_chunksize) { if (max_chunksize < MINIMUM_CHUNK_SIZE) { printf("ERROR: minimum chunk size is %i bytes\n", MINIMUM_CHUNK_SIZE); return NULL; } // 1) malloc in extmem void* extmem_out_buffer = ebsp_ext_malloc(nbytes); if (extmem_out_buffer == 0) { printf("ERROR: not enough memory in extmem for ebsp_get_buffered\n"); return NULL; } // 2) add stream to state _ebsp_add_stream(src_core_id, extmem_out_buffer, nbytes, max_chunksize, 0); return extmem_out_buffer; }
void* bsp_stream_create(int stream_size, int token_size, const void* initial_data) { if (token_size < MINIMUM_CHUNK_SIZE) { printf("ERROR: minimum token size is %i bytes\n", MINIMUM_CHUNK_SIZE); return 0; } if (state.combuf.nstreams == MAX_N_STREAMS) { printf("ERROR: Reached limit of %d streams.\n", MAX_N_STREAMS); return 0; } // Amount of tokens, rounded up int ntokens = (stream_size + token_size - 1) / token_size; int nbytes_including_headers = stream_size + ntokens * 2 * sizeof(int) + 2 * sizeof(int); // the +2*sizeof(int) is the terminating header // headers consist of 2 ints: prev size and next size // 1) malloc in extmem void* extmem_buffer = ebsp_ext_malloc(nbytes_including_headers); if (extmem_buffer == 0) { printf("ERROR: not enough memory in extmem for ebsp_stream_create\n"); return 0; } // 2) copy the data to extmem, inserting headers unsigned dst_cursor = (unsigned)extmem_buffer; unsigned src_cursor = (unsigned)initial_data; if (initial_data) { int current_chunksize = token_size; int last_chunksize = 0; for (int nbytes_left = stream_size; nbytes_left > 0; nbytes_left -= token_size) { if (nbytes_left < token_size) current_chunksize = nbytes_left; (*(int*)dst_cursor) = last_chunksize; // write prev header dst_cursor += sizeof(int); (*(int*)dst_cursor) = current_chunksize; // write next header dst_cursor += sizeof(int); memcpy((void*)dst_cursor, (void*)src_cursor, current_chunksize); dst_cursor += current_chunksize; src_cursor += current_chunksize; last_chunksize = current_chunksize; } // Write a terminating header (*(int*)dst_cursor) = current_chunksize; // write terminating header (prev) dst_cursor += sizeof(int); (*(int*)dst_cursor) = 0; // write terminating header (next) dst_cursor += sizeof(int); } else { // Write a single terminating header, or upstreams will crash (*(int*)dst_cursor) = 0; // prevsize dst_cursor += sizeof(int); (*(int*)dst_cursor) = 0; // nextsize dst_cursor += sizeof(int); } // 3) add stream to combuf ebsp_stream_descriptor x; x.extmem_addr = _arm_to_e_pointer(extmem_buffer); x.cursor = x.extmem_addr; x.nbytes = nbytes_including_headers; x.max_chunksize = token_size; x.pid = -1; memset(&x.e_dma_desc, 0, sizeof(ebsp_dma_handle)); x.current_buffer = NULL; x.next_buffer = NULL; state.shared_streams[state.combuf.nstreams] = x; state.combuf.nstreams++; return extmem_buffer; }