uint32_t endpoint_channel_get_fillstate(struct endpoint *ep) { return ep->buffer->size - endpoint_channel_get_credit(ep) - 1; }
// 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; } }