bool MicroBenchMath::time_32bit_integers() { PERF("int32 add", i_32_out += i_32, 1000); PERF("int32 sub", i_32_out -= i_32, 1000); PERF("int32 mul", i_32_out *= i_32, 1000); PERF("int32 div", i_32_out /= i_32, 1000); return true; }
bool MicroBenchMath::time_64bit_integers() { PERF("int64 add", i_64_out += i_64, 1000); PERF("int64 sub", i_64_out -= i_64, 1000); PERF("int64 mul", i_64_out *= i_64, 1000); PERF("int64 div", i_64_out /= i_64, 1000); return true; }
bool MicroBenchMath::time_8bit_integers() { PERF("int8 add", i_8_out += i_8, 1000); PERF("int8 sub", i_8_out -= i_8, 1000); PERF("int8 mul", i_8_out *= i_8, 1000); PERF("int8 div", i_8_out /= i_8, 1000); return true; }
bool MicroBenchMath::time_16bit_integers() { PERF("int16 add", i_16_out += i_16, 1000); PERF("int16 sub", i_16_out -= i_16, 1000); PERF("int16 mul", i_16_out *= i_16, 1000); PERF("int16 div", i_16_out /= i_16, 1000); return true; }
bool MicroBenchMath::time_double_precision_float() { PERF("double add", f64_out += f64, 1000); PERF("double sub", f64_out -= f64, 1000); PERF("double mul", f64_out *= f64, 1000); PERF("double div", f64_out /= f64, 1000); PERF("double sqrt", f64_out = sqrt(f64), 1000); return true; }
bool MicroBenchMath::time_single_precision_float() { PERF("float add", f32_out += f32, 1000); PERF("float sub", f32_out -= f32, 1000); PERF("float mul", f32_out *= f32, 1000); PERF("float div", f32_out /= f32, 1000); PERF("float sqrt", f32_out = sqrtf(f32), 1000); return true; }
bool MicroBenchMath::time_double_precision_float_trig() { PERF("sin()", f64_out = sin(f64), 1000); PERF("cos()", f64_out = cos(f64), 1000); PERF("tan()", f64_out = tan(f64), 1000); PERF("acos()", f64_out = acos(f64 * 0.5), 1000); PERF("asin()", f64_out = asin(f64 * 0.6), 1000); PERF("atan2()", f64_out = atan2(f64 * 0.7, f64 * 0.8), 1000); PERF("sqrt()", f64_out = sqrt(f64), 1000); return true; }
bool MicroBenchMath::time_single_precision_float_trig() { PERF("sinf()", f32_out = sinf(f32), 1000); PERF("cosf()", f32_out = cosf(f32), 1000); PERF("tanf()", f32_out = tanf(f32), 1000); PERF("acosf()", f32_out = acosf(f32), 1000); PERF("asinf()", f32_out = asinf(f32), 1000); PERF("atan2f()", f32_out = atan2f(f32, 2.0f * f32), 1000); return true; }
bool MicroBenchORB::time_px4_uorb() { int fd_status = orb_subscribe(ORB_ID(vehicle_status)); int fd_lpos = orb_subscribe(ORB_ID(vehicle_local_position)); int fd_gyro = orb_subscribe(ORB_ID(sensor_gyro)); int ret = 0; bool updated = false; uint64_t time = 0; PERF("orb_check vehicle_status", ret = orb_check(fd_status, &updated), 1000); PERF("orb_stat vehicle_status", ret = orb_stat(fd_status, &time), 1000); PERF("orb_copy vehicle_status", ret = orb_copy(ORB_ID(vehicle_status), fd_status, &status), 1000); PERF("orb_check vehicle_local_position", ret = orb_check(fd_lpos, &updated), 1000); PERF("orb_stat vehicle_local_position", ret = orb_stat(fd_lpos, &time), 1000); PERF("orb_copy vehicle_local_position", ret = orb_copy(ORB_ID(vehicle_local_position), fd_lpos, &lpos), 1000); PERF("orb_check sensor_gyro", ret = orb_check(fd_gyro, &updated), 1000); PERF("orb_stat sensor_gyro", ret = orb_stat(fd_gyro, &time), 1000); PERF("orb_copy sensor_gyro", ret = orb_copy(ORB_ID(sensor_gyro), fd_gyro, &lpos), 1000); PERF("orb_exists sensor_accel 0", ret = orb_exists(ORB_ID(sensor_accel), 0), 100); PERF("orb_exists sensor_accel 1", ret = orb_exists(ORB_ID(sensor_accel), 1), 100); PERF("orb_exists sensor_accel 2", ret = orb_exists(ORB_ID(sensor_accel), 2), 100); PERF("orb_exists sensor_accel 3", ret = orb_exists(ORB_ID(sensor_accel), 3), 100); PERF("orb_exists sensor_accel 4", ret = orb_exists(ORB_ID(sensor_accel), 4), 100); orb_unsubscribe(fd_status); orb_unsubscribe(fd_lpos); orb_unsubscribe(fd_gyro); return true; }
errval_t send_message(char *msg, size_t size, coreid_t dest) { assert(barray[dest] != NULL); struct rcce_state *st = barray[dest]->st; errval_t err; #ifdef RCCE_PERF_MEASURE dispatcher_handle_t handle = curdispatcher(); struct dispatcher_shared_generic* d = get_dispatcher_shared_generic(handle); #endif dprintf("%d: S(%lu,%d,%p,%d)\n", my_core_id, size, dest, st, st->waitmsg); #ifdef BULK_TRANSFER_ENABLED // XXX: Assert we can always send a big buffer as bulk data for performance // reasons if(size > BLOCK_SIZE) { /* printf("size = %lu, BLOCK_SIZE = %u\n", size, BLOCK_SIZE); */ } // assert(size <= BLOCK_SIZE); #endif PERF(0); // Wait til previous message has been processed by receiver #ifdef BULK_TRANSFER_ENABLED while(st->waitmsg || st->bulk_waitmsg || !st->recv_ready) { #else while(st->waitmsg) { #endif dprintf("waiting\n"); messages_wait_and_handle_next(); } st->recv_ready = false; PERF(1); #ifndef BULK_TRANSFER_ENABLED st->waitmsg = true; // Send via UMP st->request_done = false; PERF(2); err = barray[dest]-> tx_vtbl.message_request(barray[dest], MKCONT(message_request_cont,st), my_core_id, (uint8_t *)msg, size); assert(err_is_ok(err)); PERF(16); while(!st->request_done) { /* printf("%d: handling\n", my_core_id); */ messages_wait_and_handle_next(); } PERF(17); #else /* printf("recv ready, sending %d\n", msg[0]); */ // Send via bulk transfer for(size_t i = 0; i < size; i += BLOCK_SIZE) { struct bulk_buf *bb = bulk_alloc(&st->bt); assert(bb != NULL); void *buf = bulk_buf_get_mem(bb); size_t sendsize = i + BLOCK_SIZE < size ? BLOCK_SIZE : size - i; bool last_fragment = i + BLOCK_SIZE < size ? false : true; memcpy(buf, msg + i, sendsize); char *bf = buf; /* printf("send to %p (%d), msg = %p, i = %lu, sendsize = %lu\n", buf, bf[0], msg, i, sendsize); */ uintptr_t id = bulk_prepare_send(bb); st->bulk_waitmsg = true; err = barray[dest]->tx_vtbl. bulk_message_request(barray[dest], NOP_CONT, my_core_id, id, size, last_fragment); assert(err_is_ok(err)); while(st->bulk_waitmsg) { dprintf("waiting for bulk reply\n"); messages_wait_and_handle_next(); } } #endif return SYS_ERR_OK; } static void wait(void) { while (!round) { messages_wait_and_handle_next(); } round = false; } void barrier_wait(void) { switch(my_role) { case MSG_WAIT_MSG_WAIT: message(); wait(); message(); wait(); break; case WAIT_MSG_WAIT_MSG: wait(); message(); wait(); message(); break; default: assert(!"should not get here"); } } void barrier_binding_init(struct rcce_binding *binding) { binding->rx_vtbl.ring_request = ring_request; binding->rx_vtbl.ring_reply = ring_reply; binding->rx_vtbl.message_request = message_request; binding->rx_vtbl.message_reply = message_reply; #ifdef BULK_TRANSFER_ENABLED binding->rx_vtbl.bulk_message_request = bulk_message_request; binding->rx_vtbl.bulk_message_reply = bulk_message_reply; binding->rx_vtbl.bulk_recv_ready = bulk_recv_ready; #endif }
int RCCE_recv(char *privbuf, size_t size, int source) { errval_t err; #ifdef MEASURE_TIME double recv_start = RCCE_wtime(); #endif #ifdef RCCE_PERF_MEASURE dispatcher_handle_t handle = curdispatcher(); struct dispatcher_shared_generic* d = get_dispatcher_shared_generic(handle); #endif if (source<0 || source >= RCCE_NP) { return(RCCE_error_return(RCCE_debug_comm,RCCE_ERROR_ID)); } int core_id = RC_COREID[source]; struct msg_buf *mb = &msgbuf[core_id]; #ifdef BULK_TRANSFER_ENABLED mb->bulk_ready = true; mb->length = size; mb->current = 0; mb->msg = privbuf; #endif dprintf("%d: R(%lu,%d,%p,%d,%p)\n", my_core_id, size, source, mb, mb->pending, privbuf); #ifdef BULK_TRANSFER_ENABLED err = barray[core_id]->tx_vtbl.bulk_recv_ready(barray[core_id], NOP_CONT, my_core_id, size); assert(err_is_ok(err)); #endif PERF(30); while(!mb->pending) { messages_wait_and_handle_next(); } PERF(31); dprintf("%d: msg arrived\n", my_core_id); /* if(size <= DEFAULT_UMP_BUFLEN) { */ #ifndef BULK_TRANSFER_ENABLED assert(size == mb->length); memcpy(privbuf, mb->msg, size); /* } else { */ #else assert(mb->bulk); #endif /* } */ mb->pending = false; #ifndef BULK_TRANSFER_ENABLED assert(!mb->bulk); free(mb->msg); PERF(32); err = barray[core_id]->tx_vtbl.message_reply(barray[core_id], NOP_CONT, my_core_id); PERF(33); assert(err_is_ok(err)); #else assert(mb->bulk); #endif #ifdef MEASURE_TIME measure_rcce_time += RCCE_wtime() - recv_start; #endif return (RCCE_SUCCESS); }