int ebsp_open_up_stream(void** address, unsigned stream_id) { if (stream_id >= coredata.local_nstreams) { ebsp_message(err_no_such_stream); return 0; } ebsp_stream_descriptor* stream = &coredata.local_streams[stream_id]; if (stream->is_down_stream) { ebsp_message(err_mixed_up_down); return 0; } if (stream->current_buffer != NULL) { ebsp_message(err_create_opened); return 0; } stream->current_buffer = ebsp_malloc(stream->max_chunksize + sizeof(int)); if (stream->current_buffer == NULL) { ebsp_message(err_out_of_memory); return 0; } (*address) = (void*)((unsigned)stream->current_buffer + sizeof(int)); // Set the size to max_chunksize int* header = (int*)stream->current_buffer; header[0] = stream->max_chunksize; stream->cursor = stream->extmem_addr; return stream->max_chunksize; }
void ebsp_close_up_stream(unsigned stream_id) { if (stream_id >= coredata.local_nstreams) { ebsp_message(err_no_such_stream); return; } ebsp_stream_descriptor* out_stream = &coredata.local_streams[stream_id]; if (out_stream->is_down_stream) { ebsp_message(err_mixed_up_down); return; } if (out_stream->current_buffer == NULL) { ebsp_message(err_close_closed); return; } // wait for data transfer to finish before closing ebsp_dma_handle* desc = (ebsp_dma_handle*)&out_stream->e_dma_desc; ebsp_dma_wait(desc); ebsp_free(out_stream->current_buffer); out_stream->current_buffer = NULL; if (out_stream->next_buffer != NULL) { ebsp_free(out_stream->next_buffer); out_stream->next_buffer = NULL; } }
void ebsp_close_down_stream(unsigned stream_id) { if (stream_id >= coredata.local_nstreams) { ebsp_message(err_no_such_stream); return; } ebsp_stream_descriptor* in_stream = &coredata.local_streams[stream_id]; if (!(in_stream->is_down_stream)) { ebsp_message(err_mixed_up_down); return; } if (in_stream->current_buffer == NULL) { ebsp_message(err_close_closed); return; } ebsp_dma_handle* desc = (ebsp_dma_handle*)&in_stream->e_dma_desc; ebsp_dma_wait(desc); ebsp_free(in_stream->current_buffer); in_stream->current_buffer = NULL; if (in_stream->next_buffer != NULL) { ebsp_free(in_stream->next_buffer); in_stream->next_buffer = NULL; } }
void ebsp_move_down_cursor(int stream_id, int jump_n_chunks) { if (stream_id >= coredata.local_nstreams) { ebsp_message(err_no_such_stream); return; } ebsp_stream_descriptor* in_stream = &coredata.local_streams[stream_id]; if (jump_n_chunks > 0) // jump forward { while (jump_n_chunks--) { // read 2nd int in (next size) header from ext size_t chunk_size = *(int*)(in_stream->cursor + sizeof(int)); if (chunk_size == 0) { ebsp_message(err_jump_out_of_bounds); return; } in_stream->cursor = (void*)(((unsigned)(in_stream->cursor)) + 2 * sizeof(int) + chunk_size); } } else // jump backward { while (jump_n_chunks++) { // read 1st int in (prev size) header from ext int chunk_size = *(int*)(in_stream->cursor); if (chunk_size == 0) { ebsp_message(err_jump_out_of_bounds); return; } in_stream->cursor = (void*)(((unsigned)(in_stream->cursor)) - 2 * sizeof(int) - chunk_size); } } }
int ebsp_open_down_stream(void** address, unsigned stream_id) { if (stream_id >= coredata.local_nstreams) { ebsp_message(err_no_such_stream); return 0; } ebsp_stream_descriptor* stream = &coredata.local_streams[stream_id]; if (!stream->is_down_stream) { ebsp_message(err_mixed_up_down); return 0; } if (stream->current_buffer != NULL || stream->next_buffer != NULL) { ebsp_message(err_open_opened); return 0; } stream->cursor = stream->extmem_addr; // this will be the current buffer when move_chunk_down gets called for // the first time stream->next_buffer = ebsp_malloc(stream->max_chunksize + 2 * sizeof(int)); if (stream->next_buffer == NULL) { ebsp_message(err_out_of_memory); return 0; } _ebsp_write_chunk(stream, stream->next_buffer); *address = (void*)((unsigned)stream->next_buffer + 2 * sizeof(int)); return stream->max_chunksize; }
void _ebsp_write_chunk(ebsp_stream_descriptor* stream, void* target) { // read header from ext int prev_size = *(int*)(stream->cursor); int chunk_size = *(int*)(stream->cursor + sizeof(int)); if (chunk_size != 0) // stream has not ended { void* dst = target + 2 * sizeof(int); void* src = stream->cursor + 2 * sizeof(int); // jump over header+chunk stream->cursor = (void*)(((unsigned)(stream->cursor)) + 2 * sizeof(int) + chunk_size); // If token is too large, truncate it. // However DO jump the correct distance with cursor if (chunk_size > stream->max_chunksize) { ebsp_message(err_token_size2, chunk_size, stream->max_chunksize); chunk_size = stream->max_chunksize; } ebsp_dma_push(&stream->e_dma_desc, dst, src, chunk_size); } // copy it to local // we do NOT do this with the DMA because of the // possible trunction done above *(int*)(target) = prev_size; *(int*)(target + sizeof(int)) = chunk_size; }
int main() { bsp_begin(); int var = bsp_pid(); int* unregistered_var = (int*)0x7000; char teststr[] = "Default test string!"; char goodstr[] = "Replacement string."; bsp_push_reg(&var, sizeof(int)); if (bsp_pid() != 2) bsp_sync(); bsp_push_reg(teststr, sizeof(int)); // Only core 2 will do both registrations in the same sync if (bsp_pid() == 2) bsp_sync(); // expect: ($02: BSP ERROR: multiple bsp_push_reg calls within one sync) if (bsp_pid() == 1) { bsp_hpput(0, &var, &var, 0, sizeof(int)); bsp_hpput(0, &var, unregistered_var, 0, sizeof(int)); // Error // expect: ($01: BSP ERROR: could not find bsp var 0x7000) } if (bsp_pid() == 0) { bsp_hpput(1, goodstr, teststr, 0, 19 * sizeof(char)); } bsp_sync(); if (bsp_pid() == 0) ebsp_message("%d", var); // expect: ($00: 1) bsp_sync(); if (bsp_pid() == 1) ebsp_message(teststr); // expect: ($01: Replacement string.!) bsp_end(); return 0; }
int main() { bsp_begin(); int n = bsp_nprocs(); int p = bsp_pid(); ebsp_message("Hello world from core %d/%d", p, n); bsp_end(); return 0; }
void ebsp_reset_down_cursor(int stream_id) { if (stream_id >= coredata.local_nstreams) { ebsp_message(err_no_such_stream); return; } ebsp_stream_descriptor* in_stream = &coredata.local_streams[stream_id]; size_t chunk_size = -1; // break when previous block has size 0 (begin of stream) while (chunk_size != 0) { // read 1st int in (prev size) header from ext chunk_size = *(int*)(in_stream->cursor); in_stream->cursor = (void*)(((unsigned)(in_stream->cursor)) - 2 * sizeof(int) - chunk_size); } }
void EXT_MEM_TEXT bsp_send(int pid, const void* tag, const void* payload, int nbytes) { unsigned int index; unsigned int payload_offset; unsigned int total_nbytes = coredata.tagsize + nbytes; ebsp_message_queue* q = &combuf->message_queue[coredata.read_queue_index ^ 1]; e_mutex_lock(0, 0, &coredata.payload_mutex); index = q->count; payload_offset = combuf->data_payloads.buffer_size; if ((payload_offset + total_nbytes > MAX_PAYLOAD_SIZE) || (index >= MAX_MESSAGES)) { index = -1; payload_offset = -1; } else { q->count++; combuf->data_payloads.buffer_size += total_nbytes; } e_mutex_unlock(0, 0, &coredata.payload_mutex); if (index == -1) return ebsp_message(err_send_overflow); // We are now ready to save the request and payload void* tag_ptr = &combuf->data_payloads.buf[payload_offset]; payload_offset += coredata.tagsize; void* payload_ptr = &combuf->data_payloads.buf[payload_offset]; q->message[index].pid = pid; q->message[index].tag = tag_ptr; q->message[index].payload = payload_ptr; q->message[index].nbytes = nbytes; ebsp_memcpy(tag_ptr, tag, coredata.tagsize); ebsp_memcpy(payload_ptr, payload, nbytes); }
int main() { bsp_begin(); int s = bsp_pid(); std::vector<int> vec = {5, 7, 12}; MySubClass<int> b; b.foo(17); for (auto i : vec) { if (s < 4) b.bar(nullptr); else if (s < 8) b.bar(func); else b.bar([&i](int x) { ebsp_message("lambda i = %d, x = %d", i, x); }); } bsp_end(); return 0; }
void func(int a) { ebsp_message("func a = %d", a); }
void bar(std::function<void(T)> f) const { if (f) f(value); else ebsp_message("nullptr passed to MySubClass::bar"); }
int ebsp_move_chunk_down(void** address, unsigned stream_id, int prealloc) { if (stream_id >= coredata.local_nstreams) { ebsp_message(err_no_such_stream); return 0; } ebsp_stream_descriptor* stream = &coredata.local_streams[stream_id]; ebsp_dma_handle* desc = (ebsp_dma_handle*)(&(stream->e_dma_desc)); // if(stream->current_buffer == NULL) // stream->current_buffer = // ebsp_malloc(stream->max_chunksize + 2*sizeof(int)); // Here: current_buffer contains data from previous chunk // this can be null the first time ebsp_move_chunk_down is called if (!(stream->is_down_stream)) { ebsp_message(err_mixed_up_down); return 0; } if (stream->next_buffer == NULL) // did not prealloc last time { // overwrite current buffer _ebsp_write_chunk(stream, stream->current_buffer); } else // did prealloc last time { void* tmp = stream->current_buffer; stream->current_buffer = stream->next_buffer; stream->next_buffer = tmp; } // either wait for dma_push from last prealloc (else) // or the one we just started (if) ebsp_dma_wait(desc); // Here: current_buffer contains data from THIS chunk // *address must point after the counter header (*address) = (void*)((unsigned)stream->current_buffer + 2 * sizeof(int)); // the counter header int current_chunk_size = *((int*)((unsigned)stream->current_buffer + sizeof(int))); if (current_chunk_size == 0) // stream has ended { (*address) = NULL; return 0; } if (prealloc) { if (stream->next_buffer == NULL) { // no next buffer available, malloc it stream->next_buffer = ebsp_malloc(stream->max_chunksize + 2 * sizeof(int)); if (stream->next_buffer == NULL) { ebsp_message(err_out_of_memory); return 0; } } _ebsp_write_chunk(stream, stream->next_buffer); } else { // free malloced next buffer if (stream->next_buffer != NULL) { ebsp_free(stream->next_buffer); stream->next_buffer = NULL; } } // Here: next_buffer should (possibly) point to data of NEXT // chunk (begin written to) or be zero return current_chunk_size; }
int ebsp_move_chunk_up(void** address, unsigned stream_id, int prealloc) { if (stream_id >= coredata.local_nstreams) { ebsp_message(err_no_such_stream); return 0; } ebsp_stream_descriptor* stream = &coredata.local_streams[stream_id]; if (stream->is_down_stream) { ebsp_message(err_mixed_up_down); return 0; } ebsp_dma_handle* desc = (ebsp_dma_handle*)&stream->e_dma_desc; // if we prealloced last time, we have to wait until dma is finished if (stream->next_buffer != NULL) { ebsp_dma_wait(desc); } if (prealloc) { if (stream->next_buffer == NULL) { stream->next_buffer = ebsp_malloc(stream->max_chunksize + sizeof(int)); if (stream->next_buffer == NULL) { ebsp_message(err_out_of_memory); return 0; } } // read int header from current_buffer (next size) int chunk_size = ((int*)stream->current_buffer)[0]; void* src = (void*)((unsigned)stream->current_buffer + sizeof(int)); void* dst = stream->cursor; ebsp_dma_push(desc, dst, src, chunk_size); // start dma // ebsp_dma_start(); void* tmp = stream->current_buffer; // swap buffers stream->current_buffer = stream->next_buffer; stream->next_buffer = tmp; stream->cursor += chunk_size; // move pointer in extmem } else // no prealloc { if (stream->next_buffer != NULL) { ebsp_free(stream->next_buffer); stream->next_buffer = NULL; } // read int header from current_buffer (next size) int chunk_size = ((int*)stream->current_buffer)[0]; void* src = (void*)((unsigned)stream->current_buffer + sizeof(int)); void* dst = stream->cursor; ebsp_dma_push(desc, dst, src, chunk_size); // start dma // ebsp_dma_start(); ebsp_dma_wait(desc); stream->cursor += chunk_size; // move pointer in extmem } (*address) = (void*)((unsigned)stream->current_buffer + sizeof(int)); // Set the out_size to max_chunksize *((int*)(stream->current_buffer)) = stream->max_chunksize; return stream->max_chunksize; }