Пример #1
0
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];
}
Пример #2
0
// 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;
}
Пример #3
0
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);
    }
}
Пример #4
0
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);
}
Пример #5
0
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);
}
Пример #6
0
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;
}
Пример #7
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];
}
Пример #8
0
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;
}
Пример #9
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;
}
Пример #10
0
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);
    }
}
Пример #11
0
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;
}
Пример #12
0
// 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;
    }
}