Mercurial > hg > Game > Cerium
view TaskManager/Cell/CellDmaManager.cc @ 2022:fac44ad2867d draft
make a sound
author | Masataka Kohagura <kohagura@cr.ie.u-ryukyu.ac.jp> |
---|---|
date | Wed, 16 Jul 2014 02:50:32 +0900 |
parents | e0d465efc57e |
children |
line wrap: on
line source
//#include <stdio.h> #include <stdlib.h> #include "CellDmaManager.h" #include "Scheduler.h" unsigned long long alloc_flag = 0; /** * DMA Load * * @param[in] buf Buffer of Load Data * @param[in] addr Address of Load Data at Main Memory * @param[in] size Size of Load Data * @param[in] mask DMA tag */ void *CellDmaManager::dma_load(Scheduler *s, memaddr addr, uint32 size, uint32 mask) { void *buf = 0; if (size == 0) return buf; buf = s->manager->allocate(size); mfc_get((volatile void *)buf, addr, size, mask, 0, 0); return buf; } void *CellDmaManager::dma_load1(void *buf, memaddr addr, uint32 size, uint32 mask) { if (size == 0) return buf; mfc_get((volatile void *)buf, addr, size, mask, 0, 0); return buf; } void * CellDmaManager::get_writebuf(Scheduler *s,memaddr addr, uint32 size) { void *b = s->manager->allocate(size); return b; } /** * DMA Store * * @param[in] buf Buffer of Store Data at SPE * @param[in] addr Address of Store Data at Main Memory * @param[in] size Size of Store Data * @param[in] mask DMA tag */ void* CellDmaManager::dma_store(Scheduler *s,void *buf, memaddr addr, uint32 size, uint32 mask) { if (size == 0) return buf; mfc_put((volatile void *)buf, addr, size, mask, 0, 0); return buf; } void CellDmaManager::dma_wait(uint32 mask) { (this->*start_dmawait_profile)(); mfc_write_tag_mask(1 << mask); mfc_write_tag_update_all(); mfc_read_tag_status(); __asm__ __volatile__(" sync"); (this->*end_dmawait_profile)(&global_wait_time); } #ifndef MAIL_QUEUE void CellDmaManager::mail_write(memaddr data) { (this->*start_dmawait_profile)(); spu_write_out_mbox((uint32)data); #if 0 if (ABIBIT>32) { unsigned long data0 = (unsigned long)data; spu_write_out_mbox((uint32)(data0>>32)); } #endif (this->*end_dmawait_profile)(&global_mail_time); } #else // mail を queue にしたみた。mailの書き出しの待ちあるのかわからないけど //TASK_LIST_MAIL は仕事が最後に溜まってしまうけど、MailQueueなら出来る時にmailを書き出す //ので多少は効果あるといいな。 void CellDmaManager::mail_write(memaddr data) { unsigned long long wait = 0; if (0 != spu_readchcnt(SPU_WrOutMbox)) { if (mail_queue->count()) { (this->*start_dmawait_profile)(); spu_write_out_mbox((uint32)data); (this->*end_dmawait_profile)(&wait); mail_write_time += wait; global_wait_time += wait; } else { //mail_queue から poll する (this->*start_dmawait_profile)(); spu_write_out_mbox((uint32)mail_queue->recv()); (this->*end_dmawait_profile)(&wait); mail_write_time += wait; global_wait_time += wait; //mail_queue に加える mail_queue->send(data); } } else { mail_queue->send(data); } } #endif // tasklist がもうない場合に、MailQueue 全部を書き出す void CellDmaManager::mail_write_finish_list(memaddr data) { unsigned long long wait = 0; while (mail_queue->count()) { (this->*start_dmawait_profile)(); spu_write_out_mbox((uint32)mail_queue->recv()); (this->*end_dmawait_profile)(&wait); global_mail_time += wait; finish_mail_write_time += wait; } (this->*start_dmawait_profile)(); spu_write_out_mbox((uint32)data); (this->*end_dmawait_profile)(&wait); global_mail_time += wait; finish_mail_write_time += wait; } memaddr CellDmaManager::mail_read() { unsigned long long wait = 0; (this->*start_dmawait_profile)(); memaddr data = (memaddr)spu_read_in_mbox(); #if 0 if (ABIBIT>32) { data += (spu_read_in_mbox()<<32); } #endif (this->*end_dmawait_profile)(&wait); global_mail_time += wait; mail_read_time += wait; return data; } memaddr CellDmaManager::task_list_mail_read() { unsigned long long wait = 0; (this->*start_dmawait_profile)(); memaddr data = (memaddr)spu_read_in_mbox(); (this->*end_dmawait_profile)(&wait); task_list_mail_read_time += wait; global_mail_time += wait; task_list_read_count += 1; return data; } void *CellDmaManager::dma_loadList(Scheduler *s, ListDataPtr list, uint32 mask) { void *buff = s->manager->allocate(list->size); mfc_getl(buff, 0, list->element, sizeof(mfc_list_element_t)*list->length, mask, 0, 0); return buff; } void CellDmaManager::dma_storeList(ListDataPtr list, void *buff, uint32 mask) { mfc_putl(buff, 0, list->element, sizeof(mfc_list_element_t)*list->length, mask, 0, 0); } CellDmaManager::CellDmaManager() { mail_queue = new MailManager(); stop_profile(); } void CellDmaManager::start_profile() { global_busy_time = 0; global_mail_time = 0; global_wait_time = 0; task_list_mail_read_time = 0; finish_mail_write_time = 0; task_list_read_count = 0; mail_read_time = 0; mail_write_time = 0; start_dmawait_profile = &CellDmaManager::do_start_dmawait_profile; end_dmawait_profile = &CellDmaManager::do_end_dmawait_profile; } void CellDmaManager::stop_profile() { start_dmawait_profile = &CellDmaManager::null_start_dmawait_profile; end_dmawait_profile = &CellDmaManager::null_end_dmawait_profile; } /** * DMA Wait * * @param[in] mask Tag for Wait DMA process */ void CellDmaManager::do_start_dmawait_profile() { wait_time = spu_readch(SPU_RdDec); global_busy_time += busy_time - wait_time; //printf("busy_time = %d, wait_time = %d\n", busy_time, wait_time); spu_writech(SPU_WrDec, 0xffffffff); // Measurement of mainMem_alloc mainMemalloc_time += (alloc_busy_time - wait_time)*alloc_flag; } void CellDmaManager::do_end_dmawait_profile(unsigned long long *counter) { wait_time = spu_readch(SPU_RdDec); //printf("wait_time = %d", wait_time); *counter += 0xffffffff - wait_time; busy_time = wait_time; // Measurement of mainMem_alloc alloc_busy_time = wait_time; } void CellDmaManager::null_start_dmawait_profile() {} void CellDmaManager::null_end_dmawait_profile(unsigned long long *counter) {} void CellDmaManager::show_dma_wait(Scheduler *s, int cpu) { double r = ((double)global_busy_time)/((double)( global_busy_time+global_wait_time+global_mail_time ))*100.0; double d = ((double)global_wait_time)/((double)( global_busy_time+global_wait_time+global_mail_time ))*100.0; double m = ((double)global_mail_time)/((double)( global_busy_time+global_wait_time+global_mail_time ))*100.0; double tr = ((double)task_list_mail_read_time)/((double)( global_busy_time+global_wait_time+global_mail_time ))*100.0; double tw = ((double)finish_mail_write_time)/((double)( global_busy_time+global_wait_time+global_mail_time ))*100.0; double mr = ((double)mail_read_time)/((double)( global_busy_time+global_wait_time+global_mail_time ))*100.0; double mw = ((double)mail_write_time)/((double)( global_busy_time+global_wait_time+global_mail_time ))*100.0; s->printf("spu%d:\n busy_time = %lld" " wait_time = %lld(%.3g%%), " " mail_time = %lld(%.3g%%), " " mail_read_time = %lld(%.3g%%), " " mail_write_time = %lld(%.3g%%),\n" " task_list_mail_read_time = %lld(%.3g%%), " " finish_mail_write_time = %lld(%.3g%%) " " busy_ratio = %.3g%%, \n" " task_list_read_count = %d" " average_tasklist_mail_time = %lld" " mainMem_alloc_time = %lld\n" ,cpu, global_busy_time, global_wait_time, d, global_mail_time, m, mail_read_time, mr, mail_write_time, mw, task_list_mail_read_time, tr, finish_mail_write_time, tw, r, task_list_read_count, task_list_mail_read_time / task_list_read_count, mainMemalloc_time); global_busy_time = 0; global_mail_time = 0; global_wait_time = 0; mail_read_time = 0; mail_write_time = 0; task_list_mail_read_time = 0; finish_mail_write_time = 0; task_list_read_count = 0; mainMemalloc_time = 0; alloc_flag = 0; } uint32 CellDmaManager::get_tag() { static int tag = 16; tag ++; tag &= 0x0f; return tag+16; } /** * DMA buffer offset in rbuf */ void CellDmaManager::bound(ListData *list) { ListElement *elm = list->element; int *bound = list->bound; int offset=0; for(int i=0;i<list->length;i++) { bound[i] = offset; offset += elm[i].size; } } /* end */