uint32_t control_msg_alloc(struct endpoint_handle *to_ep, uint32_t size) { trace_msg_alloc_begin(to_ep, size); // Wait until receive_endpoint is ready to receive (allocate) do { // Try to retrieve from remote // We do this as long as we do not get a valid handle back (-1) ctrl_request.buffer[0] = (to_ep->domain << OPTIMSOC_DEST_LSB) | (1 << OPTIMSOC_CLASS_LSB) | (optimsoc_get_tileid() << OPTIMSOC_SRC_LSB) | (CTRL_REQUEST_MSG_ALLOC_REQ << CTRL_REQUEST_LSB); ctrl_request.buffer[1] = (unsigned int) to_ep->ep; ctrl_request.buffer[2] = (unsigned int) size; ctrl_request.done = 0; trace_msg_alloc_req_send(to_ep, size); optimsoc_mp_simple_send(3,ctrl_request.buffer); while (ctrl_request.done == 0) {} if (ctrl_request.buffer[1]==CTRL_REQUEST_NACK) { #ifdef RUNTIME thread_yield(); #endif for (int t=0;t<timeout_insns;t++) { asm __volatile__("l.nop 0x0"); } timeout_insns = timeout_insns * 10; // somewhat arbitrary.. } } while (ctrl_request.buffer[1]==CTRL_REQUEST_NACK); trace_msg_alloc_end(to_ep, ctrl_request.buffer[2]); return ctrl_request.buffer[2]; }
// Get an endpoint from the list by its metainformation struct endpoint_handle *endpoint_get(unsigned int domain, unsigned int node, unsigned int port) { struct endpoint_handle *eph = 0; // Try to find endpoint in local database struct endpoint_handle_listelem *lit; for (lit=eplist_first;lit!=0;lit=lit->next) { if ((lit->handle->domain == domain) && (lit->handle->node == node) && (lit->handle->port == port)) { eph = lit->handle; break; } } if (eph == 0 && (domain != optimsoc_get_tileid())) { // Endpoint is not locally known struct endpoint *ep = control_get_endpoint(domain, node, port); // Create the respective handle eph = malloc(sizeof(struct endpoint_handle)); eph->domain = domain; eph->node = node; eph->port = port; eph->ep = ep; eph->type = REMOTE; endpoint_add(eph); } return eph; }
void control_channel_send(struct endpoint_handle *ep, uint8_t *data, uint32_t size) { unsigned int words = (size+3)>>2; unsigned int wordsperpacket = optimsoc_noc_maxpacketsize()-4; for (int i=0;i<words;i=i+wordsperpacket) { ctrl_request.buffer[0] = (ep->domain << OPTIMSOC_DEST_LSB) | (1 << OPTIMSOC_CLASS_LSB) | (optimsoc_get_tileid() << OPTIMSOC_SRC_LSB) | (CTRL_REQUEST_CHAN_DATA << CTRL_REQUEST_LSB); ctrl_request.buffer[1] = (unsigned int) ep->ep; ctrl_request.buffer[2] = i; if (((i+wordsperpacket) >= words)) { ctrl_request.buffer[3] = size - i * wordsperpacket; } else { ctrl_request.buffer[3] = 0; } int sz = words - i; if (sz>wordsperpacket) sz = wordsperpacket; for (int d=0;d<sz;d++) { ctrl_request.buffer[4+d] = ((unsigned int *)data)[i+d]; } optimsoc_mp_simple_send(4+sz,ctrl_request.buffer); } }
void control_msg_data(struct endpoint_handle *ep, uint32_t address, void* buffer, uint32_t size) { // TODO: what if size%4!=0? assert(size % 4 == 0); trace_msg_data_begin(ep, address, size); unsigned int words = (size+3)>>2; unsigned int wordsperpacket = optimsoc_noc_maxpacketsize()-4; for (int i=0;i<words;i=i+wordsperpacket) { ctrl_request.buffer[0] = (ep->domain << OPTIMSOC_DEST_LSB) | (1 << OPTIMSOC_CLASS_LSB) | (optimsoc_get_tileid() << OPTIMSOC_SRC_LSB) | (CTRL_REQUEST_MSG_DATA << CTRL_REQUEST_LSB); ctrl_request.buffer[1] = (unsigned int) ep->ep; ctrl_request.buffer[2] = (uint32_t) address; ctrl_request.buffer[3] = i; int sz = words - i; if (sz>wordsperpacket) sz = wordsperpacket; for (int d=0;d<sz;d++) { ctrl_request.buffer[2+d] = ((unsigned int *)buffer)[i+d]; } trace_msg_data_send(ep, ctrl_request.buffer[2], sz); optimsoc_mp_simple_send(2+sz,ctrl_request.buffer); } ctrl_request.buffer[0] = (ep->domain << OPTIMSOC_DEST_LSB) | (1 << OPTIMSOC_CLASS_LSB) | (optimsoc_get_tileid() << OPTIMSOC_SRC_LSB) | (CTRL_REQUEST_MSG_COMPLETE << CTRL_REQUEST_LSB); ctrl_request.buffer[1] = (unsigned int) ep->ep; ctrl_request.buffer[2] = (uint32_t) address; ctrl_request.buffer[3] = size; trace_msg_complete_send(ep, address, size); optimsoc_mp_simple_send(4, ctrl_request.buffer); trace_msg_data_end(ep); }
void control_channel_sendcredit(struct endpoint_handle *ep, int32_t credit) { ctrl_request.buffer[0] = (ep->ep->remotedomain << OPTIMSOC_DEST_LSB) | (1 << OPTIMSOC_CLASS_LSB) | (optimsoc_get_tileid() << OPTIMSOC_SRC_LSB) | (CTRL_REQUEST_CHAN_CREDIT << CTRL_REQUEST_LSB); ctrl_request.buffer[1] = (unsigned int) ep->ep->remote; ctrl_request.buffer[2] = credit; optimsoc_mp_simple_send(3, ctrl_request.buffer); }
int lcd_set(unsigned int row,unsigned int col,char c) { uint32_t buffer = 0; if (optimsoc_has_uart() && optimsoc_uart_lcd_enable()) { set_bits(&buffer, optimsoc_uarttile(), OPTIMSOC_DEST_MSB, OPTIMSOC_DEST_LSB); set_bits(&buffer, 0, OPTIMSOC_CLASS_MSB, OPTIMSOC_CLASS_LSB); set_bits(&buffer, optimsoc_get_tileid(), OPTIMSOC_SRC_MSB, OPTIMSOC_SRC_LSB); set_bits(&buffer, 1, 13, 13); set_bits(&buffer, row, 12, 12); set_bits(&buffer, col, 11, 8); set_bits(&buffer, (uint32_t) c, 7, 0); optimsoc_mp_simple_send(1,&buffer); } return 0; }
uint32_t control_channel_connect(struct endpoint_handle *from, struct endpoint_handle *to) { ctrl_request.buffer[0] = (to->domain << OPTIMSOC_DEST_LSB) | (1 << OPTIMSOC_CLASS_LSB) | (optimsoc_get_tileid() << OPTIMSOC_SRC_LSB) | (CTRL_REQUEST_CHAN_CONNECT_REQ << CTRL_REQUEST_LSB); ctrl_request.buffer[1] = (unsigned int) to->ep; ctrl_request.buffer[2] = (unsigned int) from->domain; ctrl_request.buffer[3] = (unsigned int) from->ep; ctrl_request.done = 0; optimsoc_mp_simple_send(4, ctrl_request.buffer); while (ctrl_request.done == 0) { } return ctrl_request.buffer[1]; }
int lcd_init() { uint32_t buffer = 0; set_bits(&buffer, optimsoc_uarttile(), OPTIMSOC_DEST_MSB, OPTIMSOC_DEST_LSB); set_bits(&buffer, 0, OPTIMSOC_CLASS_MSB, OPTIMSOC_CLASS_LSB); set_bits(&buffer, optimsoc_get_tileid(), OPTIMSOC_SRC_MSB, OPTIMSOC_SRC_LSB); set_bits(&buffer, 1, 13, 13); set_bits(&buffer, ' ', 7, 0); for (int r=0;r<=1;r++) { set_bits(&buffer, r, 12, 12); for (int c=0;c<16;c++) { set_bits(&buffer, c, 11, 8); optimsoc_mp_simple_send(1,&buffer); } } return 0; }
struct endpoint *control_get_endpoint(uint32_t domain, uint32_t node, uint32_t port) { struct endpoint *ep; while (!optimsoc_mp_simple_ctready(domain)); trace_ep_get_req_begin(domain, node, port); do { // Try to retrieve from remote // We do this as long as we do not get a valid handle back (-1) ctrl_request.buffer[0] = (domain << OPTIMSOC_DEST_LSB) | (NOC_CLASS_FIFO << OPTIMSOC_CLASS_LSB) | (optimsoc_get_tileid() << OPTIMSOC_SRC_LSB) | (CTRL_REQUEST_GETEP_REQ << CTRL_REQUEST_LSB); ctrl_request.buffer[1] = node; ctrl_request.buffer[2] = port; ctrl_request.done = 0; trace_ep_get_req_send(domain, node, port); optimsoc_mp_simple_send(3,ctrl_request.buffer); control_wait_response(); ep = (struct endpoint*) ctrl_request.buffer[1]; trace_ep_get_resp_recv(domain, ep); if ((int)ep==-1) { #ifdef RUNTIME assert(0); // TODO: Reactivate //optimsoc_thread_yield(); #endif for (int t=0;t<timeout_insns;t++) { asm __volatile__("l.nop 0x0"); } timeout_insns = timeout_insns * 10; // somewhat arbitrary.. } } while ((int)ep==-1); trace_ep_get_req_end(ep); return ep; }
void uart_printf(const char *fmt, ...) { if (!optimsoc_has_uart()) { return; } char buffer[128]; va_list ap; va_start(ap, fmt); /* Initialize the va_list */ vsnprintf(buffer,128,fmt, ap); /* Call vprintf */ va_end(ap); /* Cleanup the va_list */ int size = strnlen(buffer,128); uint32_t msg = 0; set_bits(&msg, optimsoc_uarttile(), OPTIMSOC_DEST_MSB, OPTIMSOC_DEST_LSB); set_bits(&msg, 0, OPTIMSOC_CLASS_MSB, OPTIMSOC_CLASS_LSB); set_bits(&msg, optimsoc_get_tileid(), OPTIMSOC_SRC_MSB, OPTIMSOC_SRC_LSB); for (unsigned i=0;i<size;i++) { set_bits(&msg, buffer[i],7,0); optimsoc_mp_simple_send(1,&msg); } }
struct endpoint_handle *endpoint_create(uint32_t node, uint32_t port, endpoint_buffer_type buffer_type, uint32_t buffer_size, int overwrite_max_size) { struct endpoint *ep = malloc(sizeof(struct endpoint)); assert(ep!=0); ep->buffer = calloc(1, sizeof(struct endpoint_buffer)); assert(ep->buffer != 0); ep->buffer->data = malloc(buffer_size * sizeof(uint32_t*)); assert(ep->buffer->data != 0); ep->buffer->data_size = malloc(buffer_size * sizeof(uint32_t*)); assert(ep->buffer->data_size != 0); uint32_t max_element_size_bytes; uint32_t max_element_size_words; if (overwrite_max_size > 0) { max_element_size_bytes = overwrite_max_size; } else { if (buffer_type == MESSAGE) { max_element_size_bytes = MAX_MESSAGE_SIZE; } else { max_element_size_bytes = MAX_PACKET_SIZE; } } max_element_size_words = (max_element_size_bytes + 3) >> 2; uint32_t *datafield = malloc(max_element_size_bytes * buffer_size); assert(datafield); int i; for (i = 0; i < buffer_size; i++) { ep->buffer->data[i] = &datafield[i*max_element_size_words]; } ep->buffer->size = buffer_size; ep->buffer->write_ptr = 0; ep->buffer->read_ptr = 0; #ifdef RUNTIME ep->waiting = 0; #endif struct endpoint_handle *eph = malloc(sizeof(struct endpoint_handle)); assert(eph!=0); eph->ep = ep; eph->domain = optimsoc_get_tileid(); eph->node = node; eph->port = port; trace_ep_create(ep); endpoint_add(eph); return eph; }
// The following handler is called by the message interrupt service routine void control_msg_handler(unsigned int* buffer,int len) { // Extract sender information unsigned int src = EXTRACT(buffer[0],OPTIMSOC_SRC_MSB,OPTIMSOC_SRC_LSB); // Extract request type int req = EXTRACT(buffer[0],CTRL_REQUEST_MSB,CTRL_REQUEST_LSB); // Reply buffer uint32_t rbuffer[5]; // Handle the respective request switch (req) { case CTRL_REQUEST_GETEP_REQ: { trace_ep_get_req_recv(src, buffer[1], buffer[2]); // This is the request to get an endpoint handle // Flit 1: node number // Flit 2: port number // Return the get endpoint response to sender rbuffer[0] = (src << OPTIMSOC_DEST_LSB) | (1 << OPTIMSOC_CLASS_LSB) | (optimsoc_get_tileid() << OPTIMSOC_SRC_LSB) | (CTRL_REQUEST_GETEP_RESP << CTRL_REQUEST_LSB); // Get endpoint handle for <thisdomain,node,port> where // this domain is the tile id struct endpoint_handle *eph = endpoint_get(optimsoc_get_tileid(), buffer[1], buffer[2]); // If valid numbers and endpoint handle found if ( //buffer[1] < MCA_MAX_NODES && //buffer[2] < MCAPI_MAX_ENDPOINTS && (eph!=0)) { // Return endpoint rbuffer[1] = (unsigned int) eph->ep; } else { // Signal this is an invalid endpoint rbuffer[1] = (int) -1; } trace_ep_get_resp_send(src, (struct endpoint*) rbuffer[1]); optimsoc_mp_simple_send(2,rbuffer); break; } case CTRL_REQUEST_MSG_ALLOC_REQ: { rbuffer[0] = (src << OPTIMSOC_DEST_LSB) | (1 << OPTIMSOC_CLASS_LSB) | (optimsoc_get_tileid() << OPTIMSOC_SRC_LSB) | (CTRL_REQUEST_MSG_ALLOC_RESP << CTRL_REQUEST_LSB); struct endpoint *ep = (struct endpoint*) buffer[1]; unsigned int size = buffer[2]; trace_msg_alloc_req_recv(src, ep, size); uint32_t ptr; int rv = endpoint_alloc(ep, size, &ptr); if (rv == 0) { rbuffer[1] = CTRL_REQUEST_ACK; rbuffer[2] = ptr; trace_msg_alloc_resp_send(src, ep, ptr); optimsoc_mp_simple_send(3, rbuffer); } else { rbuffer[1] = CTRL_REQUEST_NACK; trace_msg_alloc_resp_send(src, ep, -1); optimsoc_mp_simple_send(2,rbuffer); } break; } case CTRL_REQUEST_MSG_DATA: { struct endpoint *ep = (struct endpoint*) buffer[1]; endpoint_write(ep, buffer[2], buffer[3], (uint32_t*) &buffer[4], len-4); break; } case CTRL_REQUEST_MSG_COMPLETE: { struct endpoint *ep = (struct endpoint*) buffer[1]; endpoint_write_complete(ep, buffer[2], buffer[3]); #ifdef RUNTIME if (ep->waiting) { thread_resume(ep->waiting_thread); ep->waiting = 0; } #endif break; } case CTRL_REQUEST_CHAN_CONNECT_REQ: { struct endpoint *ep = (struct endpoint *) buffer[1]; ep->remotedomain = (uint32_t) buffer[2]; ep->remote = (struct endpoint *) buffer[3]; rbuffer[0] = (src << OPTIMSOC_DEST_LSB) | (1 << OPTIMSOC_CLASS_LSB) | (optimsoc_get_tileid() << OPTIMSOC_SRC_LSB) | (CTRL_REQUEST_CHAN_CONNECT_RESP << CTRL_REQUEST_LSB); rbuffer[1] = endpoint_channel_get_credit(ep); optimsoc_mp_simple_send(2, rbuffer); break; } case CTRL_REQUEST_CHAN_DATA: { struct endpoint *ep = (struct endpoint *) buffer[1]; uint32_t offset = buffer[2]; uint32_t eom = buffer[3]; endpoint_write(ep, ep->buffer->write_ptr, offset, (uint32_t*) &buffer[4], len-4); if (eom) { ep->buffer->data_size[ep->buffer->write_ptr] = offset + len - 4; ep->buffer->write_ptr = _endpoint_addptrwrap(ep, ep->buffer->write_ptr, 1); trace_ep_bufferstate(ep, endpoint_channel_get_fillstate(ep)); } break; } case CTRL_REQUEST_CHAN_CREDIT: { struct endpoint *ep = (struct endpoint *) buffer[1]; uint32_t credit = buffer[2]; if (credit == 0) { ep->remotecredit = 0; } else { ep->remotecredit += credit; } break; } case CTRL_REQUEST_GETEP_RESP: case CTRL_REQUEST_MSG_ALLOC_RESP: case CTRL_REQUEST_CHAN_CONNECT_RESP: // Forward the responses to the handler ctrl_request.buffer[0] = buffer[0]; ctrl_request.buffer[1] = buffer[1]; ctrl_request.buffer[2] = buffer[2]; ctrl_request.buffer[3] = buffer[3]; ctrl_request.buffer[4] = buffer[4]; ctrl_request.done = 1; break; default: printf("Unknown request: %d\n",req); break; } }