void func_worker_1(void* arg) { // Cast and load the parameter int worker_1_param = *((int*)arg); // Create the queuing ports spd_t * chan = mp_create_sport(MP_CHAN_1_ID, SOURCE, MP_CHAN_1_MSG_SIZE); if (chan == NULL) { DEBUGF(chan); abort(); } volatile unsigned long long _SPM * time_sample = mp_alloc(MP_CHAN_1_MSG_SIZE); // Initialize the communication channels int retval = mp_init_ports(); // TODO: check on retval slave= 1; for (unsigned long long start = get_cpu_usecs(); start + RUNTIME > get_cpu_usecs(); ) { *time_sample = get_cpu_usecs(); mp_write(chan,time_sample); } int ret = 0; corethread_exit(&ret); return; }
void func_worker_1(void* arg) { mp_init(); spd_t * sport2 = mp_create_sport(CHAN_ID_TWO,SINK,SAMPLE_SIZE*sizeof(short)); spd_t * sport1 = mp_create_sport(CHAN_ID_ONE,SOURCE,SAMPLE_SIZE*sizeof(short)); if (sport1 == NULL || sport2 == NULL) { //exit(1); } volatile short _SPM * sample = mp_alloc(SAMPLE_SIZE*sizeof(short)); for (int i = 0; i < SAMPLE_SIZE; ++i) { sample[i] = i; } mp_init_ports(); while(done == 0); for (int i = 0; i < ITERATIONS; ++i) { int ret = mp_read(sport2,sample); for (int i = 0; i < SAMPLE_SIZE; ++i) { if(sample[i] != i) { break; } } for (int i = 0; i < 100000; ++i) { asm volatile (""::); } } //for (int i = 0; i < ITERATIONS/2; ++i) { for (int i = 0; i < ITERATIONS*20; ++i) { mp_write(sport1,sample); for (int i = 0; i < SAMPLE_SIZE; ++i) { sample[i] = i; } //for (int i = 0; i < 100000; ++i) { // asm volatile (""::); //} mp_write(sport1,sample); for (int i = 0; i < SAMPLE_SIZE; ++i) { sample[SAMPLE_SIZE-1-i] = i; } //for (int i = 0; i < 100000; ++i) { // asm volatile (""::); //} } int ret = 0; corethread_exit(&ret); return; }
// The main function for the other thread on the another core void work(void* arg) { // Measure execution time with the clock cycle timer volatile _IODEV int *timer_ptr = (volatile _IODEV int *) (PATMOS_IO_TIMER+4); int val, data; qpd_t *channel = mp_create_qport(1, SINK, BUF_SIZE, NUM_BUF); mp_init_ports(); for (;;) { mp_recv(channel, 0); val = *timer_ptr; data = *(volatile int _SPM *) channel->read_buf; mp_ack(channel, 0); // Return time stamp and the change value in the shared variable end_time = val; field = data + 1; } }
//Producer Core void producer(void *arg) { #ifdef MEASUREMENT_MODE // start initialization measurement timeStamps_slave1[0] = TDM_P_COUNTER;//3955 cycles #endif int id = get_cpuid(); // Data initialization int volatile data_wr[MSG_SIZE]; /////////////////////////////////////////////////////////////////////////////// // This section of the task handles with the initializations for buffering /////////////////////////////////////////////////////////////////////////////// // allocating the data into SPM qpd_t * chan1 = mp_create_qport(1, SOURCE, MP_CHAN_BUF_SIZE, MP_CHAN_NUM_BUF); mp_init_ports(); //remote address calculation at the receiver side int rmt_addr_offset = (chan1->buf_size + FLAG_SIZE) * chan1->send_ptr; volatile void _SPM *calc_rmt_addr = &chan1->recv_addr[rmt_addr_offset]; #ifdef MEASUREMENT_MODE timeStamps_slave1[1] = TDM_P_COUNTER; // stop the initialization measurement at 4888 cycles #endif for(;;){ /////////////////////////////////////////////////////////////////////////////// // Computation part of the Task. Data production /////////////////////////////////////////////////////////////////////////////// if((TDM_P_COUNTER-TRIGGER_PROD_COMP)%PROD_PERIOD == 0 ){ // Data production. at the moment we use dummy data for (int i=0;i<MSG_SIZE;i++){ data_wr[i]=i; } // writing the data to the write buffer for (int i=0;i<MSG_SIZE;i++){ *(volatile int _SPM*)((int*)chan1->write_buf+i) = data_wr[i]; } } /////////////////////////////////////////////////////////////////////////////// // Communication part of the Task. /////////////////////////////////////////////////////////////////////////////// // when the communication time is triggered if(((TDM_P_COUNTER-TRIGGER_PROD_COMM)%PROD_PERIOD) == 0 ){ #ifdef MEASUREMENT_MODE timeStamps_slave1[2] = TDM_P_COUNTER; //start the communication measurement #endif //nonblocking write transaction noc_nbwrite( (id+1),calc_rmt_addr,chan1->write_buf,chan1->buf_size + FLAG_SIZE, 0); #ifdef MEASUREMENT_MODE timeStamps_slave1[3] = TDM_P_COUNTER; //stop the communication measurement #endif }// if }//for }
// Consumer Core void consumer(void *arg) { #ifdef MEASUREMENT_MODE // start initialization measurement timeStamps_slave2[0] = TDM_P_COUNTER; #endif int id = get_cpuid(); int cnt = get_cpucnt(); int volatile data_rd[MSG_SIZE]; /////////////////////////////////////////////////////////////////////////////// // This section of the task handles with the initializations for buffering /////////////////////////////////////////////////////////////////////////////// // allocating data to SPM qpd_t * chan2 = mp_create_qport(2, SINK, MP_CHAN_BUF_SIZE, MP_CHAN_NUM_BUF); mp_init_ports(); // mp init ports #ifdef MEASUREMENT_MODE timeStamps_slave2[1] = TDM_P_COUNTER; // stop the initialization measurement #endif for(;;){ /////////////////////////////////////////////////////////////////////////////// // Communication part of the Task. /////////////////////////////////////////////////////////////////////////////// // when the time is triggered if((TDM_P_COUNTER-TRIGGER_CONS_COMM)%CONS_PERIOD == 0 ){ #ifdef MEASUREMENT_MODE timeStamps_slave2[2] = TDM_P_COUNTER;// start the communication measurement #endif // reading the data to the read buffer for (int i=0;i<MSG_SIZE;i++){ data_rd[i] = *(volatile int _SPM*)((int*)chan2->read_buf+i); // read the data } #ifdef MEASUREMENT_MODE timeStamps_slave2[3] = TDM_P_COUNTER; //stop the communication measurement #endif } /////////////////////////////////////////////////////////////////////////////// // Computation part of the Task. Perhaps for an Actuator /////////////////////////////////////////////////////////////////////////////// if(((TDM_P_COUNTER-TRIGGER_CONS_COMP)%CONS_PERIOD) == 0 ){ // make data manipulation (but for now dummy) over the data for(int i=0;i<MSG_SIZE;i++){ data_rd[i] += 100; } }//if /////////////////////////////////////////////////////////////////////////////// //Print the received data for debuging /////////////////////////////////////////////////////////////////////////////// #define DEBUG_PRINT_CONS #ifdef DEBUG_PRINT_CONS for(int i=0;i<MSG_SIZE;i++){ debug_print_cons[i] = data_rd[i]; } #endif }//for }
// Intermediate Core void intermediate(void *arg) { #ifdef MEASUREMENT // start initialization measurement timeStamps_slave2[0] = TDM_P_COUNTER; #endif int id = get_cpuid(); // Data initialization int volatile data[MSG_SIZE]; /////////////////////////////////////////////////////////////////////////////// // This section of the task handles with the initializations for buffering /////////////////////////////////////////////////////////////////////////////// // allocating the data into SPM buffers qpd_t * chan1 = mp_create_qport(1, SINK, MP_CHAN_BUF_SIZE, MP_CHAN_NUM_BUF); qpd_t * chan2 = mp_create_qport(2, SOURCE, MP_CHAN_BUF_SIZE, MP_CHAN_NUM_BUF); mp_init_ports(); // mp init ports //remote address calculation int rmt_addr_offset = (chan2->buf_size + FLAG_SIZE) * chan2->send_ptr; volatile void _SPM *calc_rmt_addr = &chan2->recv_addr[rmt_addr_offset]; #ifdef MEASUREMENT timeStamps_slave2[1] = TDM_P_COUNTER; // stop the initialization measurement #endif for(;;){ /////////////////////////////////////////////////////////////////////////////// // Communication part of the Task. /////////////////////////////////////////////////////////////////////////////// // when the time is triggered read from read-buffer if((TDM_P_COUNTER-TRIGGER_INTM_COMM_READ)%PROD_PERIOD == 0 ){ #ifdef MEASUREMENT timeStamps_slave2[2] = TDM_P_COUNTER;// start the communication measurement #endif // reading the data from the read-buffer for (int i=0;i<MSG_SIZE;i++){ data[i] = *(volatile int _SPM*)((int*)chan1->read_buf+i); } #ifdef MEASUREMENT timeStamps_slave2[3] = TDM_P_COUNTER; //stop the communication measurement #endif } /////////////////////////////////////////////////////////////////////////////// // Computation part of the Task. Data manipulation /////////////////////////////////////////////////////////////////////////////// if((TDM_P_COUNTER-TRIGGER_INTM_COMP)%PROD_PERIOD == 0 ){ // make data manipulation (but for now dummy) over the data for(int i=0;i<MSG_SIZE;i++){ data[i] += 10; } // writing the data to the write-buffer for (int i=0;i<MSG_SIZE;i++){ *(volatile int _SPM*)((int*)chan2->write_buf+i) = data[i]; } } /////////////////////////////////////////////////////////////////////////////// // Communication part of the Task. /////////////////////////////////////////////////////////////////////////////// // when the time is triggered write to write-buffer if((TDM_P_COUNTER-TRIGGER_INTM_COMM_WRITE)%PROD_PERIOD == 0 ){ #ifdef MEASUREMENT timeStamps_slave2[4] = TDM_P_COUNTER; //start the communication measurement #endif //nonblocking write transaction noc_nbwrite( (id+1),calc_rmt_addr,chan2->write_buf,chan2->buf_size + FLAG_SIZE, 0); #ifdef MEASUREMENT timeStamps_slave2[5] = TDM_P_COUNTER; //stop the communication measurement #endif }// if /////////////////////////////////////////////////////////////////////////////// //Print the received data for debuging /////////////////////////////////////////////////////////////////////////////// #define DEBUG_PRINT_INTERM #ifdef DEBUG_PRINT_INTERM for(int i=0;i<MSG_SIZE;i++){ debug_print_interm[i] = data[i]; } #endif }//for }
int main() { puts("Master"); corethread_t worker_1 = 1; // For now the core ID int worker_1_param = 1; corethread_create(&worker_1,&func_worker_1,(void*)&worker_1_param); // Create the queuing ports spd_t * chan = mp_create_sport(MP_CHAN_1_ID, SINK, MP_CHAN_1_MSG_SIZE); volatile unsigned long long _SPM * time_sample = mp_alloc(MP_CHAN_1_MSG_SIZE); if (chan == NULL || time_sample == NULL) { DEBUGF(chan); abort(); } // Initialize the communication channels int retval = mp_init_ports(); // TODO: check on retval puts("Initialized ports"); while(slave != 1) { ; } puts("Slave is ready"); unsigned long long min_time_diff = -1; unsigned long long max_time_diff = 0; unsigned long long accum_time_diff = 0; unsigned long long cnt_time_diff = 0; unsigned long long percent = 0; int done = 0; unsigned long long start = get_cpu_usecs(); while(!done) { int success = mp_read(chan,time_sample); unsigned long long time_diff = get_cpu_usecs() - (*time_sample); if (success == 0) { printf("No sample received\n"); } else if ((*time_sample) == 0) { printf("Received empty sample, newest: %u, sample size: %u\n",chan->newest,chan->sample_size); } else { if (time_diff > 2000 ) { // Time difference is larger than a micro second printf("Time sample: %llu\tdiff: %llu\n",*time_sample,time_diff); } cnt_time_diff++; if (time_diff < min_time_diff) { min_time_diff = time_diff; } if (time_diff > max_time_diff) { max_time_diff = time_diff; } accum_time_diff += time_diff; } if (start + percent < get_cpu_usecs()) { percent += RUNTIME/10; printf("+"); fflush(stdout); } if ( start + RUNTIME < get_cpu_usecs()) { done = 1; } } printf("\n"); printf("Status:\n\tMin time diff: %llu\n\tMax time diff: %llu\n\tAvg time diff: %llu\n", min_time_diff,max_time_diff,accum_time_diff/cnt_time_diff); int* res; corethread_join(worker_1,&res); return *res; }
int main() { corethread_t worker_1 = SLAVE_CORE; // For now the core ID corethread_create(&worker_1,&func_worker_1,(void*)&worker_1); puts("Corethread created"); unsigned short int local_phase = 0; min_time = ULONG_MAX; max_time = 0; accum_time = 0; cnt_time = 0; unsigned long long int start = 0; unsigned long long int stop = 0; spd_t * sport1 = mp_create_sport(CHAN_ID_ONE,SINK,SAMPLE_SIZE*sizeof(short)); spd_t * sport2 = mp_create_sport(CHAN_ID_TWO,SOURCE,SAMPLE_SIZE*sizeof(short)); if (sport1 == NULL || sport2 == NULL) { //exit(1); } volatile short _SPM * sample = mp_alloc(SAMPLE_SIZE*sizeof(short)); mp_init_ports(); done = 1; int balance = 0; for (int i = 0; i < SAMPLE_SIZE; ++i) { sample[i] = i; } for (int i = 0; i < ITERATIONS/2; ++i) { mp_write(sport2,sample); for (int i = 0; i < SAMPLE_SIZE; ++i) { sample[i] = i; } } for (int i = 0; i < ITERATIONS/2; ++i) { mp_write(sport2,sample); for (int i = 0; i < SAMPLE_SIZE; ++i) { sample[SAMPLE_SIZE-1-i] = i; } } for (int i = 0; i < ITERATIONS; ++i) { start = get_cpu_usecs(); int ret = mp_read(sport1,sample); stop = get_cpu_usecs(); if (ret == 0) { puts("No value written yet."); } else { unsigned long long int exe_time = stop - start; min_time = (exe_time < min_time) ? exe_time : min_time; max_time = (exe_time > max_time) ? exe_time : max_time; accum_time += exe_time; cnt_time++; if (sample[0] == 0) { balance++; for (int i = 0; i < SAMPLE_SIZE; ++i) { if(sample[i] != i) { printf("Error: sample[%i] = %i\n",i,sample[i]); break; } } } else if (sample[0] == SAMPLE_SIZE-1) { balance--; for (int i = 0; i < SAMPLE_SIZE; ++i) { if(sample[SAMPLE_SIZE-1-i] != i) { printf("Error: sample[%i] = %i\n",i,sample[i]); break; } } } else { printf("Wrong sample values sample[0] = %i\n",sample[0]); } } } printf("Local phase: %d\n",local_phase); inval_dcache(); int* res; corethread_join(worker_1,&res); printf("Balance: %i\n",balance); printf("Min time: %llu\tMax time: %llu\tAccumulated time: %llu\nCount time: %llu\tAverage time: %llu\n", min_time,max_time,accum_time,cnt_time,accum_time/cnt_time); puts("Corethread joined"); return *res; }
void bench_noc() { // Pointer to the deadline device volatile _IODEV int *dead_ptr = (volatile _IODEV int *) PATMOS_IO_DEADLINE; // Measure execution time with the clock cycle timer volatile _IODEV int *timer_ptr = (volatile _IODEV int *) (PATMOS_IO_TIMER+4); printf("Hello NoC\n"); printf("We use %d bytes buffers\n", BUF_SIZE); int core_id = 1; // The core number corethread_create(core_id, &work, NULL); int start, val; int data = 42; // create a channel qpd_t *channel = mp_create_qport(1, SOURCE, BUF_SIZE, NUM_BUF); // init mp_init_ports(); start = *timer_ptr; // write data into the send buffer *(volatile int _SPM *) channel->write_buf = data; start = *timer_ptr; // send the buffer mp_send(channel, 0); printf("Data sent\n"); printf("Returned data is: %d\n", field); printf("Took %d cycles\n", end_time - start - 1); int min = 999999; int max = 0; printf("NoC in a loop:\n"); for (int i=0; i<CNT; ++i) { start = *timer_ptr; *(volatile int _SPM *) channel->write_buf = i; start = *timer_ptr; mp_send(channel, 0); *dead_ptr = 10000; // some delay to see the result val = *dead_ptr; val = end_time - start - 1; // printf("%d ", val); if (min>val) min = val; if (max<val) max = val; } printf("\n"); printf("Min: %d max: %d\n", min, max); min = 999999; max = 0; do_delay_times(); printf("NoC in a loop with random delay:\n"); for (int i=0; i<CNT; ++i) { start = *timer_ptr; *(volatile int _SPM *) channel->write_buf = i; *dead_ptr = data_spm[i]; val = *dead_ptr; // delay by a random value start = *timer_ptr; mp_send(channel, 0); *dead_ptr = 3000; // some delay to see the result val = *dead_ptr; val = end_time - start; // printf("%d ", val); if (min>val) min = val; if (max<val) max = val; } printf("\n"); printf("Min: %d max: %d\n", min, max); // not really as the worker runs forever int* res; corethread_join( core_id, (void *) &res ); }