view TaskManager/Cell/spe/CellDmaManager.cc @ 1025:cb170249c752

minor fix
author yutaka@localhost.localdomain
date Mon, 08 Nov 2010 14:40:53 +0900
parents 19a57960c436
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(void *buf, memaddr addr, uint32 size, uint32 mask)
{
    if (size == 0) return ;
    mfc_get((volatile void *)buf, addr, size, mask, 0, 0);


}

/**
 * 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(void *buf, memaddr addr, uint32 size, uint32 mask)
{
    if (size == 0) return ;
    mfc_put((volatile void *)buf, addr, size, mask, 0, 0);
}

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);
  
}

void CellDmaManager::dma_wait(uint32 mask, int cmd)
{

    unsigned long long wait = 0;

    (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)(&wait);

    global_wait_time += wait;

  if (cmd == TaskArray) {
    task_array_load_time += wait;
  } else if (cmd == TaskArray1) {
  }

}

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);
}

// mail を queue にしたみた。mailの書き出しの待ちあるのかわからないけど
//TASK_LIST_MAIL は仕事が最後に溜まってしまうけど、MailQueueなら出来る時にmailを書き出す
//ので多少は効果あるといいな。
void CellDmaManager::mail_write_queue(memaddr data)
{
    (this->*start_dmawait_profile)();

    if (0 != spu_readchcnt(SPU_WrOutMbox)) {
      if (mail_queue->count()) {
          spu_write_out_mbox((uint32)data);
      } else {

	//mail_queue から poll する
	spu_write_out_mbox((uint32)mail_queue->recv());
	//mail_queue に加える
	mail_queue->send(data);

      }
    } else {

      mail_queue->send(data);

    }
    (this->*end_dmawait_profile)(&global_mail_time);
}

// tasklist おわりに、MailQueue 全部を書き出す
void CellDmaManager::mail_write_finish_list(memaddr data)
{

    (this->*start_dmawait_profile)();

    while (mail_queue->count()) {

      spu_write_out_mbox((uint32)mail_queue->recv());      

    }

    spu_write_out_mbox((uint32)data);

    (this->*end_dmawait_profile)(&global_mail_time);


}

memaddr CellDmaManager::mail_read()
{


    (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)(&global_mail_time);



    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_time += wait;
    global_mail_time += wait;

    return data;
}



void CellDmaManager::dma_loadList(ListDataPtr list, void *buff, uint32 mask)
{
    mfc_getl(buff, 0, list->element, sizeof(mfc_list_element_t)*list->length,
	     mask, 0, 0);
}

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_array_load_time = 0;
    task_list_mail_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;

    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);
    *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 t = ((double)task_list_mail_time)/((double)(
	global_busy_time+global_wait_time+global_mail_time
	))*100.0;


  s->printf("spu%d: busy_time = %lld"
  " wait_time = %lld(%.3g%%), "
  " mail_time = %lld(%.3g%%), " 
  " task_list_mail_time = %lld(%.3g%%), " 
  " busy_ratio = %.3g%%, "
  " array_load_time = %lld, "
  " mainMem_alloc_time = %lld\n"
    ,cpu, global_busy_time,
    global_wait_time, d, global_mail_time, m, 
    task_list_mail_time, t, r,
    task_array_load_time,
    mainMemalloc_time);

    global_busy_time = 0;
    global_mail_time = 0;
    global_wait_time = 0;
    task_array_load_time = 0;
    task_list_mail_time = 0;
    mainMemalloc_time = 0;
    alloc_flag = 0;
}


/* end */