00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013 #ifndef _MEMORY_CHANNEL_H
00014 #define _MEMORY_CHANNEL_H
00015
00016 #ifndef MEMORYCHANNEL_DBG
00017 #define MEMORYCHANNEL_DBG 0
00018 #endif
00019
00020 #define _MC_DBG( fmt, args... ) \
00021 m_dbg.write( "%s():%d: "fmt, __FUNCTION__, __LINE__, ##args)
00022
00023 #include <sst/elements/include/eventChannel.h>
00024 #include <map>
00025
00026 using namespace SST;
00027
00028 template < typename addrT = unsigned long,
00029 typename dataT = unsigned long >
00030 struct MemEvent
00031 {
00032 typedef enum { READ = 0, WRITE, RMW, INV_REQ } reqType_t;
00033 typedef enum { REQUEST = 0, RESPONSE, INV_MSG } msgType_t;
00034
00035 typedef dataT data_t;
00036 typedef addrT addr_t;
00037
00038 reqType_t reqType;
00039 msgType_t msgType;
00040 addr_t addr;
00041 data_t data;
00042 };
00043
00044 template < typename addrT = unsigned long,
00045 typename cookieT = unsigned long,
00046 typename dataT = unsigned long >
00047 class MemoryChannel :
00048 public EventChannel< MemEvent< addrT, dataT > >
00049 {
00050 public:
00051
00052 typedef MemEvent< addrT, dataT > event_t;
00053 typedef typename event_t::addr_t addr_t;
00054 typedef dataT data_t;
00055 typedef cookieT cookie_t;
00056
00057 private:
00058 typedef std::multimap< addr_t, cookie_t> reqMap_t;
00059 typedef EventChannel< MemEvent< addrT, dataT > > eventChannel_t;
00060
00061 public:
00062
00063 virtual ~MemoryChannel() {;}
00064 MemoryChannel( Component& comp, Component::Params_t params,
00065 std::string name ) :
00066 eventChannel_t( comp, params, name, 2 ),
00067 m_readReqCredit( 0 ),
00068 m_readRespCredit( 0 ),
00069 m_writeReqCredit( 0 ),
00070 m_writeRespCredit( 0 ),
00071 m_log( *new Log<>( "INFO MemoryChannel::", false ) ),
00072 m_dbg( *new Log< MEMORYCHANNEL_DBG >( "MemoryChannel::", false ) )
00073 {
00074 if ( params.find("debug") != params.end() ) {
00075 if ( params["debug"].compare("yes") == 0 ) {
00076 m_dbg.enable();
00077 }
00078 }
00079
00080 if ( params.find("info") != params.end() ) {
00081 if ( params["info"].compare("yes") == 0 ) {
00082 m_log.enable();
00083 }
00084 }
00085
00086 if ( params.find("readReqCredit") != params.end() ) {
00087 m_readReqCredit = str2long( params["readReqCredit"] );
00088 }
00089 if ( params.find("writeReqCredit") != params.end() ) {
00090 m_writeReqCredit = str2long( params["writeReqCredit"] );
00091 }
00092 if ( params.find("readRespCredit") != params.end() ) {
00093 m_readRespCredit = str2long( params["readRespCredit"] );
00094 }
00095 if ( params.find("writeRespCredit") != params.end() ) {
00096 m_writeRespCredit = str2long( params["writeRespCredit"] );
00097 }
00098
00099 m_log.write( "readReqCredit=%d readRespCredit=%d\n",
00100 m_readReqCredit, m_readRespCredit );
00101 m_log.write( "writeReqCredit=%d writeRespCredit=%d\n",
00102 m_writeReqCredit, m_writeRespCredit );
00103 }
00104
00105 virtual inline bool ready( typename event_t::msgType_t msgType,
00106 typename event_t::reqType_t reqType = event_t::READ )
00107 {
00108 return eventChannel_t::ready(
00109 calcCredit( msgType, reqType ), msgType );
00110 }
00111
00112 virtual inline bool send( event_t* event, cookie_t cookie = 0 )
00113 {
00114 return send( event, event->msgType, event->reqType,
00115 event->addr, cookie );
00116 }
00117
00118 virtual inline bool recv( event_t** event, cookie_t* cookie = 0 )
00119 {
00120 if ( recv( event, event_t::RESPONSE, cookie ) ) {
00121 return true;
00122 }
00123 return recv( event, event_t::REQUEST, cookie );
00124 }
00125
00126 virtual inline bool send( event_t* event,
00127 typename event_t::msgType_t msgType,
00128 typename event_t::reqType_t reqType,
00129 addr_t addr, cookie_t cookie = 0 )
00130 {
00131 _MC_DBG("event=%p cookie=%#lx type=%d:%d \n", event, cookie,
00132 msgType, reqType );
00133
00134 int tokens = calcCredit( msgType, reqType );
00135 if ( ! eventChannel_t::ready( tokens, msgType ) ) {
00136 return false;
00137 }
00138
00139 if ( cookie ) {
00140 storeCookie( reqType, cookie, addr );
00141 }
00142
00143 return eventChannel_t::send( event, tokens, msgType );
00144 }
00145
00146 virtual inline bool recv( event_t** event,
00147 typename event_t::msgType_t type,
00148 cookie_t* cookie = 0 )
00149 {
00150 if ( ! eventChannel_t::recv( event, type ) ) {
00151 return false;
00152 }
00153
00154 if ( cookie && (*event)->msgType == event_t::RESPONSE ) {
00155 *cookie = findCookie( (*event)->reqType, (*event)->addr );
00156 }
00157
00158 _MC_DBG("event=%p cookie=%#lx\n", *event, cookie );
00159 return true;
00160 }
00161
00162 private:
00163 inline int calcCredit( typename event_t::msgType_t msgType,
00164 typename event_t::reqType_t reqType )
00165 {
00166 if ( msgType == event_t::REQUEST ) {
00167 if ( reqType == event_t::READ ) {
00168 return m_readReqCredit;
00169 } else {
00170 return m_writeReqCredit;
00171 }
00172 } else {
00173 if ( reqType == event_t::READ ) {
00174 return m_readRespCredit;
00175 } else {
00176 return m_writeRespCredit;
00177 }
00178 }
00179 }
00180
00181 inline void storeCookie( typename event_t::reqType_t type,
00182 cookie_t cookie, addr_t addr )
00183 {
00184 if ( type == event_t::WRITE ) {
00185 m_writeReqMap.insert( std::make_pair( addr, cookie ) );
00186 } else {
00187 m_readReqMap.insert( std::make_pair( addr, cookie ) );
00188 }
00189 }
00190
00191 inline cookie_t findCookie( typename event_t::reqType_t type,
00192 addr_t addr )
00193 {
00194 typename reqMap_t::iterator iter;
00195 if ( type == event_t::WRITE ) {
00196 iter = m_writeReqMap.find( addr );
00197 if ( iter != m_writeReqMap.end() ) {
00198 m_writeReqMap.erase(iter);
00199 return iter->second;
00200 }
00201 } else {
00202 iter = m_readReqMap.find( addr );
00203 if ( iter != m_readReqMap.end() ) {
00204 m_readReqMap.erase(iter);
00205 return iter->second;
00206 }
00207 }
00208 return 0;
00209 }
00210
00211 private:
00212
00213 reqMap_t m_writeReqMap;
00214 reqMap_t m_readReqMap;
00215 int m_readReqCredit;
00216 int m_readRespCredit;
00217 int m_writeReqCredit;
00218 int m_writeRespCredit;
00219
00220 Log<>& m_log;
00221 Log< MEMORYCHANNEL_DBG >& m_dbg;
00222 };
00223
00224 #endif