|
libraries/onchipcommunication/systemc/Router.hGo 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 1.5.4 |