00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013 #include <sst/elements/include/paramUtil.h>
00014
00015 #define _EC_DBG( fmt, args... ) \
00016 m_dbg.write( "%s():%d: "fmt, __FUNCTION__, __LINE__, ##args)
00017
00018 EVENTCHANNEL()::EventChannel( Component& comp,
00019 Component::Params_t params, std::string name, int numVC ) :
00020 m_component( comp ),
00021 m_log( *new Log< >( "INFO EventChannel: ", false ) ),
00022 m_dbg( *new Log< EVENTCHANNEL_DBG >( "EventChannel::", false ) )
00023 {
00024 _EC_DBG("\n");
00025
00026 if ( params.find("info") != params.end() ) {
00027 if ( params["info"].compare("yes") == 0 ) {
00028 m_log.enable();
00029 }
00030 }
00031
00032 bool dbgFlag = false;
00033 if ( params.find("debug") != params.end() ) {
00034 if ( params["debug"].compare("yes") == 0 ) {
00035 m_dbg.enable();
00036 dbgFlag = true;
00037 }
00038 }
00039
00040 EventHandler_t* handler = new EventHandler< EventChannel, bool, Event* >
00041 ( this, &EventChannel::handler );
00042
00043 if ( ! handler ) {
00044 _abort( EventChannel, "new EventHandler failed\n" );
00045 }
00046
00047 m_log.write("creating link \"%s\"\n", name.c_str());
00048 Link* link = comp.LinkAdd( name, handler );
00049
00050 m_vcV.resize( numVC );
00051
00052 int startCredit = 0;
00053 int threshold = 0;
00054 if ( params.find("initialCredit") != params.end() ) {
00055 startCredit = str2long( params["initialCredit"] );
00056 }
00057
00058 for ( int i = 0; i < numVC; i++ ) {
00059 m_vcV[i] = new VirtChan( i, *link, comp.type, dbgFlag,
00060 startCredit, threshold );
00061 }
00062
00063 ClockHandler_t* clockHandler;
00064 clockHandler = new EventHandler< EventChannel, bool, Cycle_t >
00065 ( this, &EventChannel::clock );
00066
00067 std::string frequency = "1GHz";
00068 if ( params.find("clock") != params.end() ) {
00069 frequency = params["clock"];
00070 }
00071
00072 m_log.write("frequency=%s startCredit=%d\n",frequency.c_str(),startCredit );
00073
00074 TimeConverter* tc = comp.registerClock( frequency, clockHandler );
00075 if ( ! tc ) {
00076 _abort(XbarV2,"couldn't register clock handler");
00077 }
00078 }
00079
00080 EVENTCHANNEL(bool)::clock( Cycle_t cycle )
00081 {
00082 for ( unsigned int i = 0; i < m_vcV.size(); i++ ) {
00083 m_vcV[i]->clock( cycle );
00084 }
00085 return false;
00086 }
00087
00088 EVENTCHANNEL( bool )::handler( Event* e )
00089 {
00090 event_t* event = static_cast< event_t* >( e );
00091 if ( size_t(event->virtChan) > m_vcV.size() ) {
00092 _abort(EventChannel,"invalid vc=%d\n", event->virtChan );
00093 }
00094 return m_vcV[ event->virtChan ]->handler( event );
00095 }
00096
00097 EVENTCHANNEL( inline bool )::ready( int credit, int vc )
00098 {
00099 if ( size_t(vc) > m_vcV.size() ) {
00100 _abort(EventChannel,"invalid vc=%d\n", vc );
00101 }
00102 return m_vcV[ vc ]->ready( credit );
00103 }
00104
00105 EVENTCHANNEL( inline bool )::send( eventT* event, int credit, int vc )
00106 {
00107 if ( size_t(vc) > m_vcV.size() ) {
00108 _abort(EventChannel,"invalid vc=%d\n", vc );
00109 }
00110 return m_vcV[ vc ]->send( event, credit );
00111 }
00112
00113 EVENTCHANNEL( inline bool )::recv( eventT** event, int vc )
00114 {
00115 if ( size_t(vc) > m_vcV.size() ) {
00116 _abort(EventChannel,"invalid vc=%d\n", vc );
00117 }
00118 return m_vcV[ vc ]->recv( event );
00119 }
00120
00121 EVENTCHANNEL()::VirtChan::VirtChan( int vc, Link& link, std::string& name,
00122 bool dbgFlag, int startCredit, int threshold ) :
00123 m_vc( vc ),
00124 m_link( link ),
00125 m_creditAvail( startCredit ),
00126 m_creditFreed( 0 ),
00127 m_creditThreshold( threshold ),
00128 m_name( name ),
00129 m_dbg( *new Log< EVENTCHANNEL_DBG > ("EventChannel::VirtChan::", dbgFlag) )
00130 {
00131 _EC_DBG("avail=%d thres=%d\n", m_creditAvail, m_creditThreshold );
00132 }
00133
00134 EVENTCHANNEL( inline bool )::VirtChan::clock( Cycle_t cycle )
00135 {
00136 if ( ! m_outQ.empty() ) {
00137 _EC_DBG("%s: cycle=%lu send, event=%p\n", m_name.c_str(),
00138 cycle,m_outQ.front() );
00139
00140 m_link.Send( 0, m_outQ.front() );
00141 m_outQ.pop_front();
00142 }
00143
00144 if ( m_creditFreed > m_creditThreshold )
00145 {
00146 event_t* event = new event_t;
00147
00148 event->type = event_t::CREDIT;
00149 event->credit = m_creditFreed;
00150 event->virtChan = m_vc;
00151
00152 m_creditFreed = 0;
00153
00154 _EC_DBG("%s: cycle=%lu send %d credits\n",
00155 m_name.c_str(), cycle, event->credit);
00156 m_link.Send( 0, event );
00157 }
00158 return false;
00159 }
00160
00161 EVENTCHANNEL( inline bool )::VirtChan::handler( event_t* event )
00162 {
00163 if ( event->type == event_t::EVENT ) {
00164
00165 m_inQ.push_back( event );
00166 } else if ( event->type == event_t::CREDIT ) {
00167 m_creditAvail += event->credit;
00168 _EC_DBG("%s: got %d credits now avail %d\n",
00169 m_name.c_str(), event->credit, m_creditAvail );
00170 delete event;
00171 } else {
00172 _abort( WireLink, "bad event type %d\n", event->type );
00173 }
00174 return false;
00175 }
00176
00177 EVENTCHANNEL( inline bool )::VirtChan::ready( int credit )
00178 {
00179 _EC_DBG("%s: credit=%d m_createAvail=%d\n", m_name.c_str(),
00180 credit, m_creditAvail);
00181 return ( (int)m_creditAvail >= credit );
00182 }
00183
00184 EVENTCHANNEL( inline bool )::VirtChan::send( eventT* event, int credit )
00185 {
00186 if ( (int)m_creditAvail < credit ) {
00187 _EC_DBG("%s: failed, credit=%d createAvail=%d\n", m_name.c_str(),
00188 credit, m_creditAvail);
00189 return false;
00190 }
00191 _EC_DBG("%s: need credit=%d createAvail=%d\n", m_name.c_str(),
00192 credit, m_creditAvail);
00193
00194 event_t* cEvent = new event_t;
00195 cEvent->virtChan = m_vc;
00196 cEvent->event = event;
00197 cEvent->type = event_t::EVENT;
00198 cEvent->credit = credit;
00199
00200 m_outQ.push_back( cEvent );
00201
00202 m_creditAvail -= credit;
00203
00204 return true;
00205 }
00206
00207 EVENTCHANNEL( inline bool )::VirtChan::recv( eventT** event )
00208 {
00209 if ( m_inQ.empty() ) {
00210 return false;
00211 }
00212 *event = m_inQ.front()->event;
00213
00214 m_creditFreed += m_inQ.front()->credit;
00215 _EC_DBG("%s: creditFreed=%d\n",m_name.c_str(), m_creditFreed);
00216
00217 delete m_inQ.front();
00218 m_inQ.pop_front();
00219
00220 return true;
00221 }