libraries/onchipcommunication/systemc/Router.h

Go to the documentation of this file.
00001 //============================================================================
00002 // Author      : Alessandro Pinto <apinto@eecs.berkeley.edu>
00003 //               University of California, Berkeley
00004 //               545 Cory Hall, Berkeley, CA 94720
00005 // Copyright   : See COPYING file that comes with this distribution
00006 //============================================================================
00007 
00008 #ifndef ROUTER_H_
00009 #define ROUTER_H_
00010 
00011 #include "systemc.h"
00012 #include <queue>
00013 #include <map>
00014 #include <set>
00015 #include "Technology.h"
00016 
00017 using namespace std ;
00018 
00019 template< int Nin , int Nout , int FlitWidth >
00020   class Router : public sc_module 
00021 {
00022   
00023  public:
00024   
00025   sc_in< bool > Clock ;
00026   
00027   //Input ports
00028   sc_in < sc_bv< FlitWidth > > DataIn[Nin] ;
00029   sc_in < bool > ValidIn[Nin] ;
00030   sc_out< bool > AckOut[Nin] ;
00031   sc_out< bool > FullOut[Nin] ;
00032   
00033   //Output ports
00034   sc_out< sc_bv< FlitWidth > > DataOut[Nout] ;
00035   sc_out< bool > ValidOut[Nout] ;
00036   sc_in< bool > AckIn[Nout] ;
00037   sc_in< bool > FullIn[Nout] ;
00038   
00039   SC_HAS_PROCESS( Router ) ;
00040   
00041   void Fsm( ) ;
00042   void InputFsm( ) ;
00043   void SwitchFsm( ) ;
00044   void OutputFsm( ) ;
00045   void PrintState( ) ; 
00046   
00047   Router( sc_module_name n , 
00048           int T , 
00049          int Size , 
00050           map< pair<int,int> , int > RoutingTable ,
00051           vector< double > ChannelWeights ,
00052           TechnologyNode Tech) : sc_module( n ) {
00053     
00054     mTech = Tech ;
00055     mRoutingTable = RoutingTable ; 
00056     mSize = Size ;
00057     mT = T ; 
00058     mChannelWeights = ChannelWeights ;
00059     
00060     mLastGranted = 0 ;
00061     
00062     for( int i = 0 ; i < Nin ; i++ ) {
00063       mRstate[i] = RIDLE ;
00064       mState[i] = IDLE ;
00065     }
00066     
00067     for( int i = 0 ; i < Nout ; i++ ) {
00068       mWstate[i] = WIDLE ;
00069     }
00070     
00071     mInputGranted.resize( Nin , false ) ;
00072     mOutput.resize( Nin , -1 ) ;
00073     mOutputBusy.resize( Nout , false ) ;
00074     mFlitCount.resize( Nin , 0 ) ;
00075     
00076     mFIFO.resize( Nin ) ;
00077     mCurrentFlow.resize( Nin ) ;
00078     mSentFlits.resize( Nin , 0 ) ;
00079     mTotalFlitSent = 1 ;
00080     mOutputBuffer.resize( Nout ) ;
00081     mInput.resize( Nout , -1 ) ; 
00082 
00083 
00084     SC_THREAD( Fsm ) ;
00085     sensitive_pos << Clock ;
00086     
00087     mDynamicEnergy = 0 ;
00088   
00089     cout << "Router " << name( ) << " initialized " << endl ;
00090     
00091   }
00092  
00093   double GetDynamicPower( ) {
00094     return ( mDynamicEnergy/ ( sc_simulation_time( ) * 10e-9) ) ; 
00095   }
00096    
00097   TechnologyNode mTech ;
00098   map< pair<int,int> , int > mRoutingTable ;
00099   vector< double > mChannelWeights ;
00100   int mSize ;
00101   int mT ;
00102   
00103   vector< queue< sc_bv< FlitWidth > > > mFIFO ;
00104   //The outbuffer is supposed to be one place only
00105   vector< queue< sc_bv< FlitWidth > > > mOutputBuffer ;
00106 
00107   
00108   //Input states
00109   enum{ RIDLE , RX } mRstate[Nin] ; 
00110   //Output States 
00111   enum{ WIDLE , TX } mWstate[Nout] ;
00112   
00113   vector< bool > mInputGranted ; 
00114   
00115   vector< int > mOutput ;
00116   
00117   vector< int > mInput ; 
00118   
00119   vector< bool > mOutputBusy ; 
00120   
00121   vector< int > mFlitCount ; 
00122   
00123   vector<int> mSentFlits ;
00124   
00125   vector< pair<int,int> > mCurrentFlow ;
00126   
00127   int mTotalFlitSent ;
00128 
00129   //Switch state
00130   enum{ IDLE , FLIT} mState[Nin] ;
00131 
00132   int mLastGranted ;
00133 
00134   double mDynamicEnergy ;
00135 
00136 
00137 } ;
00138 
00139 
00140 template< int Nin , int Nout , int FlitWidth >
00141   void Router< Nin , Nout , FlitWidth >::PrintState( ) {
00142 
00143   cout << name( ) << endl ;
00144   cout << "Input queues " << endl ;
00145   for( int Input = 0 ; Input < Nin ; Input++ ) {
00146     cout << "Input " << Input << " size = " << mFIFO[Input].size( ) ;
00147     if ( !mState[Input] == FLIT ) {
00148       cout << " Header "  ;
00149       sc_bv< FlitWidth > Header ;
00150       Header = mFIFO[Input].front( ) ;
00151       pair<int,int> Sd ;
00152       Sd.first = ( Header.range( 7 , 0 )).to_int( )  ;
00153       Sd.second = (Header.range( 15 , 8 )).to_int( )  ;
00154       //cout << name( ) <<  " Input " << i << " competing for output " << mRoutingTable[Sd] << endl ; 
00155       cout << "Flow (" << Sd.first << "," << Sd.second << ") to output " << mRoutingTable[Sd] ;
00156     }
00157     else {
00158       cout << " Flit" << " Flow (" << mCurrentFlow[Input].first << "," << mCurrentFlow[Input].second  ;
00159     }
00160     if ( mInputGranted[Input] ) {
00161       cout << " Assigned to " << mOutput[Input] ;
00162       cout << " need to send " << mFlitCount[Input] << endl ; 
00163     } else {
00164       cout << " Not assigned " <<  endl ;
00165     }
00166   }
00167 
00168   cout << "Output queues " << endl ;
00169   for( int Output = 0 ; Output < Nout ; Output++ ) {
00170     cout << "Output " << Output << " size = " << mOutputBuffer[Output].size( )  << "  " ;
00171     if( mOutputBusy[Output] ) 
00172       cout << "Busy " << endl ;
00173     else
00174       cout << "Available" << endl ; 
00175   }
00176   
00177 }
00178 
00179 
00180 
00181 template< int Nin , int Nout , int FlitWidth >
00182   void Router< Nin , Nout , FlitWidth >::Fsm( ) {
00183  
00184   cout << "Router " << name( )  << " running " << endl ;
00185 
00186   while( true ) {
00187     
00188     //Singals from the FIFOs
00189     for( int i = 0 ; i < Nin ; i++ ) {
00190       if ( mFIFO[i].size( ) == mSize ) {
00191         FullOut[i] = true ;
00192       } else {
00193         FullOut[i] = false ;
00194       }
00195     }
00196     
00197     wait( ) ;
00198     //PrintState( ) ;
00199     InputFsm( ) ;
00200     SwitchFsm( ) ;
00201     OutputFsm( ) ;
00202   }  
00203   
00204 }
00205 
00206 template< int Nin , int Nout , int FlitWidth >
00207   void Router< Nin , Nout , FlitWidth >::InputFsm( ) {
00208   for( int Input = 0 ; Input < Nin ; Input++ ) {
00209     //receive from all inputs
00210     switch( mRstate[Input] ) {
00211     case RIDLE : 
00212       if ( ValidIn[Input] ) { //Get the Flit 
00213         mFIFO[Input].push( DataIn[Input] ) ;
00214         mRstate[Input] = RX ;
00215         AckOut[Input] = true ;
00216       }
00217       break ;
00218     case RX :
00219       AckOut[Input] = false ;
00220       mRstate[Input] = RIDLE ;
00221       break ; 
00222     }
00223   }
00224 }
00225 
00226 
00227 template< int Nin , int Nout , int FlitWidth >
00228   void Router< Nin , Nout , FlitWidth >::OutputFsm( ) {
00229   
00230   for( int Output = 0 ; Output < Nout ; Output++ ) {
00231     if ( ! mOutputBuffer[Output].empty( ) ) { 
00232       switch( mWstate[Output] ) {
00233       case WIDLE:
00234         if ( ! FullIn[Output] ) {
00235           DataOut[Output] = mOutputBuffer[Output].front( ) ;
00236           ValidOut[Output] = true ;
00237           mWstate[Output] = TX ;
00238         }
00239         break;
00240       case TX:
00241         if ( AckIn[Output] ) {
00242           ValidOut[Output] =false ;
00243           mOutputBuffer[Output].pop( ) ;
00244           mFlitCount[mInput[Output]]-- ;
00245           mSentFlits[mInput[Output]]++ ;
00246           mTotalFlitSent++ ;
00247 
00248           //Annotate dynamic energy
00249           mDynamicEnergy += mTech.Erouter[Nin][Nout] ;
00250 
00251           if ( mFlitCount[mInput[Output]] == 0 ) {
00252             mInputGranted[ mInput[Output] ] = false ;
00253             mOutputBusy[ Output ] = false ;
00254             mState[mInput[Output]] = IDLE ;
00255           }
00256           mWstate[Output] = WIDLE ;
00257         }
00258         break;
00259       }
00260     } 
00261   }
00262 }
00263 
00264 template< int Nin , int Nout , int FlitWidth >
00265   void Router< Nin , Nout , FlitWidth >::SwitchFsm( ) {
00266   
00268   //                 Channel assignment 
00270   
00271   //Compute the slacks
00272   vector< double > Slack( Nin , 0 ) ;
00273   for( int i = 0 ; i < Nin ; i++ ) {
00274     Slack[i] = ( (double)mSentFlits[i])/((double)mTotalFlitSent)  - mChannelWeights[i] ;
00275     //cout << name( ) << " Slack for input " << i << " = " << Slack[i] << endl ; 
00276   }
00277 
00278   //look for competing inputs
00279   vector< set< int > > CompetingInputs( Nout ) ;
00280   sc_bv< FlitWidth > Header ;
00281   pair<int,int> Sd ;
00282   for( int i = 0 ; i < Nin ; i++ ) {
00283     
00284     //If this input is not in any transfer and has some flits waiting 
00285     //(then in must be the header flit)
00286     
00287     if ( ( ! mInputGranted[i] ) && ( ! mFIFO[i].empty( ) ) ) {
00288       Header = mFIFO[i].front( ) ;
00289       Sd.first = ( Header.range( 7 , 0 )).to_int( )  ;
00290       Sd.second = (Header.range( 15 , 8 )).to_int( )  ;
00291       mCurrentFlow[i] = Sd ;
00292       //cout << name( ) <<  " Input " << i << " competing for output " << mRoutingTable[Sd] << endl ; 
00293       CompetingInputs[mRoutingTable[Sd]].insert( i ) ;
00294     }
00295     
00296   }
00297 
00298   //Assign each avalable output to inputs 
00299   //in decreasing order of slacks
00300   for( int i = 0 ; i < Nout ; i++ ) {
00301 
00302     if ( ! mOutputBusy[i] && ! CompetingInputs[i].empty( ) ) {
00303       //Scan the competing inputs for
00304       //minimum slacks
00305       set<int>::iterator It ;
00306       double MinSlack = DBL_MAX ; int MinIn = 0 ;
00307       for( It = CompetingInputs[i].begin( ) ; It != CompetingInputs[i].end( ) ; It++ ) {
00308         if ( Slack[*It] < MinSlack ) {
00309           MinSlack = Slack[*It] ;
00310           MinIn = *It ;
00311         }
00312       }
00313       //Assign Output
00314       //cout << name( ) << " Output " << i << " assigned to input " << MinIn << endl ;
00315       mInputGranted[ MinIn ] = true ;
00316       mOutput[ MinIn ] = i ;
00317       mInput[ i ] = MinIn ;
00318       mOutputBusy[ i ] = true ;
00319     } 
00320   }
00321   
00323   //                 Flit input to output transfer
00325   int Input ;
00326   for( Input = 0 ; Input < Nin ; Input++ ) {
00327     //If the input has been granted and the queue is not empty 
00328     if ( mInputGranted[Input]  ) {
00329       
00330       switch( mState[Input] ) {
00331       case IDLE :
00332         if ( mOutputBuffer[ mOutput[ Input ] ].size( ) == 0 && ! mFIFO[Input].empty( ) ) {
00333           //this is the header flit
00334           Header = mFIFO[Input].front( ) ;
00335           mFlitCount[Input] =  ( Header.range( 23 , 16 )).to_int( )  ;
00336           //cout << " Need to send " << mFlitCount[Input] << " flits " << endl ;
00337           //put the flit in the output buffer and wait for the transfer to finish
00338           mOutputBuffer[ mOutput[ Input ] ].push( Header ) ;
00339           mFIFO[Input].pop( ) ;
00340           mState[Input] = FLIT ;
00341         }
00342         break ;
00343       case FLIT :
00344         if ( mOutputBuffer[ mOutput[ Input ] ].size( ) == 0 && ! mFIFO[Input].empty( ) ) {
00345           //tranfer is done
00346           
00347             mOutputBuffer[ mOutput[ Input ] ].push( mFIFO[Input].front( ) ) ;
00348             //cout << " Sending flit " <<  mFlitCount[Input] << endl ;
00349             mFIFO[Input].pop( ) ;           
00350           
00351         } 
00352         break ;
00353       }
00354     }
00355   }
00356 }
00357 
00358 #endif /*ROUTER_H_*/

Generated on Sun Sep 7 18:37:42 2008 for COSI by  doxygen 1.5.4
Contact 
©2002-2018 U.C. Regents