//------------------------------------------------------------
// $Id: NetIntUnit.h,v 1.1.1.1 1999/11/25 06:26:09 yamauchi Exp $
//------------------------------------------------------------
// Network Interface Unit 
//   network interface unit 構造体 
//	操作の多くは PE にて定義される。
//	NI は他 PE の通信などこのクラスで完結しない操作を多数持ってい
//	るため、操作の多くは PE のメンバとして定義した。
//   1998年2月 1日(日)
//   1999年5月29日(土) 書き直し
//	Copyright (C) 1998-1999 YAMAUCHI Hitoshi 山内 斉
//------------------------------------------------------------
#ifndef _NetIntUnit_h
#define _NetIntUnit_h 1

#include "mySLQueue.h"
#include "ray.h"
#include "object.h"
#include "constants.h"
#include "req_handle_t.h"
#include "Intensity.h"
#include "spc2PE.h"
#include "SendBuffer.h"
#include "RecvBuffer.h"
#include "PEStat.h"
#include "HostComm.h"

//------------------------------------------------------------
// NetIntClass : Network Interface Unit の実装
//------------------------------------------------------------
class NetIntClass {
private:
    NetIntClass(const NetIntClass& rhs);
    const NetIntClass& operator=(const NetIntClass& rhs);
    
protected:
    int mTotalPENum;		 // 全 PE 数
    int mSendRayThreshold;	 // 送信キュー長がこれを越えたら ray を送信
    int	mSendIntensityThreshold; // 輝度送信キュー長がこの長さを越えたら送信
    int mThisRank;		 // この NetworkInterface の自分の rank (check)
    int mHostRank;		 // host の rank

public:
    // 空間と PE の対応情報の実体
    spc2PEBaseClass    *mpSpc2PE;

public:
    // ray の送受信用バッファ (キューイングあり): i 番目の送信用バッファ 
    // は rank == i 用 
    SendBuffer < Ray > *mpSendRaysBuf; // 送信 : 実行時に数を決定する
    RecvBuffer < Ray > mRecvRaysBuf[MAX_RECV_BUFFNUM];    // 受信:数は固定

    // ホストへの輝度送信用 buf (これは送信用が一つのみ，受信は host のみ)
    SendBuffer < IntensityClass > mSendIntensitiesBuf;

    // シェーディング時の頂点輝度送受信用バッファ
    SendBuffer < VertexIntensity > *mpSendVerIntBuf; // [i] は destrank == i 用
    RecvBuffer < VertexIntensity >  mRecvVerIntBuf;

    // ホストへの状態の送信用バッファ
    SendBuffer < PEStatClass   > mSendPEStatBuf;
    // ホストからの命令の受信バッファ
    RecvBuffer < HostCommClass > mRecvHostCommBuf;
    
public:
    NetIntClass(void);
    ~NetIntClass(void);

public: 
    //------------------------------------------------------------
    // Ray
    //------------------------------
    // initialize ray buffer
    //------------------------------
    void initRayBuff(int totalPENum,	   // 全 PE 数
		     int sendThreshold,    // ray の送信開始 ray 数
		     int sendInt2FBAtOnce, // 輝度送信まとめ送り数
		     int thisRank,	   // このNetIntを保持する PE の rank 
		     int hostRank,	   // host の rank
		     mySLQueue < Ray * > *pProcRaysQueue); //PEのキューへの参照
    //------------------------------
    // send
    //------------------------------
    // キューに入れ，その方向のキューが十分長い場合には送信
    YorN sendRays(Ray *pRay, int destRank);
    // 全ての方向を見てある方向のキューが十分長い場合には送信
    YorN sendRaysIfExceedQueueLen();
    // キューに1つでもオブジェクトが存在した場合，送信要求が発行可能ならば発行
    YorN flushSendRaysBuff(void);    
    // 送信要求で未完のものが完了したのかチェックする
    void completeSendRaysRequest(void);
    // 送信中のものはない
    YorN isNoSendRay(void);    
    // 全ての送信バッファが empty なら YES
    YorN isSendRayBufAllEmpty(void) const;

    //------------------------------
    // recv
    //------------------------------
    YorN recvRays(void);	// 受信
    YorN isNoRecvRay(void);	// 受信中のものがない場合は YES
    int  getNRecvs(void);	// 受信中のバッファ数を返す

public: 
    //------------------------------------------------------------
    // Intenisity : pixel 送信のみ (host が受信)
    //------------------------------
    // キューに設定した値を越えて保持された場合，送信要求が発行可能ならば発行
    void sendIntensity(IntensityClass *pIntensity);
    // flush queue
    void flushIntensitySendBuf(void);
    YorN isSendingIntensity(void);

public:
    //------------------------------------------------------------
    // VerInt : 頂点輝度
    //------------------------------
    // initialize verInt buffer
    //------------------------------
    void initVerIntBuff(int verIntSendThreshold, // VInt 送信時まとめ送り数
			mySLQueue < VertexIntensity * > *pVerIntRecvQueue);
    void sendVerInt(VertexIntensity *pIntensity, int destrank);
    void flushVerIntSendBuff(void);
    YorN isSendingVerInt(void);		// 送信中のものが何か存在する

    void recvVerInt(void);
    YorN isRecvingVerInt(void);		// 受信中のものが何か存在する

public:
    //------------------------------------------------------------
    // PE 情報をホストに送信
    //------------------------------
    void initPEStatHostCommBuff(mySLQueue < HostCommClass * >
				*pHostCommRecvQueue);
    void sendPEStat(PEStatClass *pIntensity);
    void flushPEStatSendBuff(void);
    YorN isSendingPEStat(void);	// 送信中のものが何か存在する

    //------------------------------------------------------------
    // ホストから PE へコマンドを受信
    //------------------------------
    void recvHostComm(void);
    YorN isRecvingHostComm(void); // 受信中のものが何か存在する

public:
    //------------------------------------------------------------
    // 統計情報の出力
    //------------------------------------------------------------
    void printStat(const char *pMes, const char *pStageName);
};

#endif				// _NetIntUnit_h
