void acquire_lock(LOCK_T * lock){ /* Write Entering true */ /* Write Number */ unsigned remote = lock->remote_cpuid; unsigned id = get_cpuid(); lock->local_entering = 1; noc_write(remote, (void _SPM *)&(lock->remote_ptr->remote_entering), (void _SPM *)&lock->local_entering, sizeof(lock->local_entering), 0); //#pragma loopbound min 1 max 2 #pragma loopbound min PKT_TRANS_WAIT max PKT_TRANS_WAIT while(!noc_dma_done(remote)); unsigned n = (unsigned)lock->remote_number + 1; lock->local_number = n; /* Enforce memory barrier */ noc_write(remote, (void _SPM *)&(lock->remote_ptr->remote_number), (void _SPM *)&lock->local_number, sizeof(lock->local_number), 0); // /* Enforce memory barrier */ #pragma loopbound min PKT_TRANS_WAIT max PKT_TRANS_WAIT while(!noc_dma_done(remote)); // noc_write() also waits for the dma to be // free, so no need to do it here as well /* Write Entering false */ lock->local_entering = 0; noc_write(remote, (void _SPM *)&(lock->remote_ptr->remote_entering), (void _SPM *)&lock->local_entering, sizeof(lock->local_entering), 0); /* Wait for remote core not to change number */ #pragma loopbound min 1 max 2 while(lock->remote_entering == 1); /* Wait to be the first in line to the bakery queue */ unsigned m = lock->remote_number; #pragma loopbound min 1 max 2 while( (m != 0) && ( (m < n) || ((m == n) && ( remote < id)))) { m = lock->remote_number; } /* Lock is grabbed */ return; }
void noc_test_slave() { // Performing libnoc test... noc_receive(); // for (int i = 0; i < 8; ++i) { // *(NOC_SPM_BASE+i) = 0x11223344 * i; // } noc_write((unsigned)NOC_MASTER,(volatile void _SPM *)(NOC_SPM_BASE+(get_cpuid()*8)),(volatile void _SPM *)NOC_SPM_BASE,32,1); while(done[NOC_MASTER] != 1){;} return; }
void release_lock(LOCK_T * lock) { /* Write Number */ lock->local_number = 0; noc_write(lock->remote_cpuid, (void _SPM *)&(lock->remote_ptr->remote_number), (void _SPM *)&lock->local_number, sizeof(lock->local_number), 0); /* Enforce memory barrier */ #pragma loopbound min PKT_TRANS_WAIT max PKT_TRANS_WAIT while(!noc_dma_done(lock->remote_cpuid)); /* Lock is freed */ return; }
void noc_test_master() { printf("Performing libnoc test..."); fflush(stdout); for (int i = 0; i < get_cpucnt(); ++i) { if (i != NOC_MASTER) { for (int j = 0; j < 8; ++j) { *(NOC_SPM_BASE+j) = 0x11223344 * i; } noc_write((unsigned)i,(volatile void _SPM *)NOC_SPM_BASE,(volatile void _SPM *)NOC_SPM_BASE,32,1); while(done[i] != 1){;} noc_receive(); for (int j = 0; j < 8; ++j){ ABORT_IF_FAIL(*(NOC_SPM_BASE+(i*8)+j) != 0x11223344 * i ,"Wrong data received"); } } } printf("OK\n"); }
static void slave(void* param) { // clear communication areas // cannot use memset() for _SPM pointers! for(int i = 0; i < sizeof(struct msg_t); i++) { ((volatile _SPM char *)spm_in)[i] = 0; ((volatile _SPM char *)spm_out)[i] = 0; } // wait and poll until message arrives while(!spm_in->ready) { /* spin */ } // PROCESS: add ID to sum_id spm_out->sum = spm_in->sum + get_cpuid(); spm_out->ready = 1; // send to next slave int rcv_id = (get_cpuid()==(get_cpucnt()-1)) ? 0 : get_cpuid()+1; noc_write(rcv_id, spm_in, spm_out, sizeof(struct msg_t), 0); return; }
static void master(void) { // reset sum spm_out->sum = 0; // the message is ready spm_out->ready = 1; // The first message must be delayed until all slaves have cleared // their SPM! Writing something does the trick. WRITE("INIT\n", 5); // send message to core 1 noc_write(get_cpuid()+1, spm_in, spm_out, sizeof(struct msg_t), 0); WRITE("SENT\n", 5); // wait and poll while(!spm_in->ready) { /* spin */ } WRITE("RCVD ", 5); static char msg[10]; msg[0] = XDIGIT((spm_in->sum >> 28) & 0xf); msg[1] = XDIGIT((spm_in->sum >> 24) & 0xf); msg[2] = XDIGIT((spm_in->sum >> 20) & 0xf); msg[3] = XDIGIT((spm_in->sum >> 16) & 0xf); msg[4] = XDIGIT((spm_in->sum >> 12) & 0xf); msg[5] = XDIGIT((spm_in->sum >> 8) & 0xf); msg[6] = XDIGIT((spm_in->sum >> 4) & 0xf); msg[7] = XDIGIT((spm_in->sum >> 0) & 0xf); msg[8] = '\n'; WRITE(msg, 9); return; }