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