multi_passthrough_target_socket.h revision 12027:1eb7dc7aa10b
111666Stushar@ece.gatech.edu/***************************************************************************** 211666Stushar@ece.gatech.edu 311666Stushar@ece.gatech.edu Licensed to Accellera Systems Initiative Inc. (Accellera) under one or 411666Stushar@ece.gatech.edu more contributor license agreements. See the NOTICE file distributed 511666Stushar@ece.gatech.edu with this work for additional information regarding copyright ownership. 611666Stushar@ece.gatech.edu Accellera licenses this file to you under the Apache License, Version 2.0 711666Stushar@ece.gatech.edu (the "License"); you may not use this file except in compliance with the 811666Stushar@ece.gatech.edu License. You may obtain a copy of the License at 911666Stushar@ece.gatech.edu 1011666Stushar@ece.gatech.edu http://www.apache.org/licenses/LICENSE-2.0 1111666Stushar@ece.gatech.edu 1211666Stushar@ece.gatech.edu Unless required by applicable law or agreed to in writing, software 1311666Stushar@ece.gatech.edu distributed under the License is distributed on an "AS IS" BASIS, 1411666Stushar@ece.gatech.edu WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or 1511666Stushar@ece.gatech.edu implied. See the License for the specific language governing 1611666Stushar@ece.gatech.edu permissions and limitations under the License. 1711666Stushar@ece.gatech.edu 1811666Stushar@ece.gatech.edu *****************************************************************************/ 1911666Stushar@ece.gatech.edu#ifndef __MULTI_PASSTHROUGH_TARGET_SOCKET_H__ 2011666Stushar@ece.gatech.edu#define __MULTI_PASSTHROUGH_TARGET_SOCKET_H__ 2111666Stushar@ece.gatech.edu 2211666Stushar@ece.gatech.edu#include "tlm_utils/multi_socket_bases.h" 2311666Stushar@ece.gatech.edu#include <sstream> 2411666Stushar@ece.gatech.edu 2511666Stushar@ece.gatech.edunamespace tlm_utils { 2611666Stushar@ece.gatech.edu 2711666Stushar@ece.gatech.edu/* 2811666Stushar@ece.gatech.eduThis class implements a trivial multi target socket. 2911666Stushar@ece.gatech.eduThe triviality refers to the fact that the socket does not 3011666Stushar@ece.gatech.edudo blocking to non-blocking or non-blocking to blocking conversions. 3111666Stushar@ece.gatech.edu 3211666Stushar@ece.gatech.eduIt allows to connect multiple initiators to this socket. 3311666Stushar@ece.gatech.eduThe user has to register callbacks for the fw interface methods 3411666Stushar@ece.gatech.eduhe likes to use. The callbacks are basically equal to the fw interface 3511666Stushar@ece.gatech.edumethods but carry an additional integer that indicates to which 3611666Stushar@ece.gatech.eduindex of this socket the calling initiator is connected. 3711666Stushar@ece.gatech.edu*/ 3811666Stushar@ece.gatech.edutemplate <typename MODULE, 3911666Stushar@ece.gatech.edu unsigned int BUSWIDTH = 32, 4011666Stushar@ece.gatech.edu typename TYPES = tlm::tlm_base_protocol_types, 4111666Stushar@ece.gatech.edu unsigned int N=0 4211666Stushar@ece.gatech.edu#if !(defined SYSTEMC_VERSION & SYSTEMC_VERSION <= 20050714) 4311797Smatthew.poremba@amd.com ,sc_core::sc_port_policy POL = sc_core::SC_ONE_OR_MORE_BOUND 4411666Stushar@ece.gatech.edu#endif 4511666Stushar@ece.gatech.edu > 4611666Stushar@ece.gatech.educlass multi_passthrough_target_socket: public multi_target_base< BUSWIDTH, 4711666Stushar@ece.gatech.edu TYPES, 4811666Stushar@ece.gatech.edu N 4911666Stushar@ece.gatech.edu#if !(defined SYSTEMC_VERSION & SYSTEMC_VERSION <= 20050714) 5011666Stushar@ece.gatech.edu ,POL 5111666Stushar@ece.gatech.edu#endif 5211666Stushar@ece.gatech.edu > 5311666Stushar@ece.gatech.edu , public multi_to_multi_bind_base<TYPES> 5411666Stushar@ece.gatech.edu{ 5511666Stushar@ece.gatech.edu 5611666Stushar@ece.gatech.edupublic: 5711666Stushar@ece.gatech.edu 5811666Stushar@ece.gatech.edu //typedefs 5911666Stushar@ece.gatech.edu // tlm 2.0 types for nb_transport 6011666Stushar@ece.gatech.edu typedef typename TYPES::tlm_payload_type transaction_type; 6111666Stushar@ece.gatech.edu typedef typename TYPES::tlm_phase_type phase_type; 6211666Stushar@ece.gatech.edu typedef tlm::tlm_sync_enum sync_enum_type; 6311666Stushar@ece.gatech.edu 6411666Stushar@ece.gatech.edu // typedefs to keep the fn ptr notations short 6511666Stushar@ece.gatech.edu typedef sync_enum_type (MODULE::*nb_cb)(int, transaction_type&, phase_type&, sc_core::sc_time&); 6611666Stushar@ece.gatech.edu typedef void (MODULE::*b_cb)(int, transaction_type&, sc_core::sc_time&); 6711666Stushar@ece.gatech.edu typedef unsigned int (MODULE::*dbg_cb)(int, transaction_type& txn); 6811666Stushar@ece.gatech.edu typedef bool (MODULE::*dmi_cb)(int, transaction_type& txn, tlm::tlm_dmi& dmi); 6911666Stushar@ece.gatech.edu 7011666Stushar@ece.gatech.edu typedef multi_target_base<BUSWIDTH, 7111666Stushar@ece.gatech.edu TYPES, 7211666Stushar@ece.gatech.edu N 7311666Stushar@ece.gatech.edu#if !(defined SYSTEMC_VERSION & SYSTEMC_VERSION <= 20050714) 7411666Stushar@ece.gatech.edu ,POL 7511666Stushar@ece.gatech.edu#endif 7611666Stushar@ece.gatech.edu > base_type; 7711666Stushar@ece.gatech.edu 7811666Stushar@ece.gatech.edu typedef typename base_type::base_initiator_socket_type base_initiator_socket_type; 7911666Stushar@ece.gatech.edu 8011666Stushar@ece.gatech.edu //CTOR 8111666Stushar@ece.gatech.edu multi_passthrough_target_socket() 8211666Stushar@ece.gatech.edu : base_type(sc_core::sc_gen_unique_name("multi_passthrough_target_socket")) 8311666Stushar@ece.gatech.edu , m_hierarch_bind(0) 8411666Stushar@ece.gatech.edu , m_eoe_disabled(false) 8511666Stushar@ece.gatech.edu , m_export_callback_created(false) 8611666Stushar@ece.gatech.edu { 87 } 88 89 //CTOR 90 multi_passthrough_target_socket(const char* name) 91 : base_type(name) 92 , m_hierarch_bind(0) 93 , m_eoe_disabled(false) 94 , m_export_callback_created(false) 95 { 96 } 97 98 ~multi_passthrough_target_socket(){ 99 //clean up everything allocated by 'new' 100 for (unsigned int i=0; i<m_binders.size(); i++) delete m_binders[i]; 101 } 102 103 //simple helpers for warnings an errors to shorten in code notation 104 void display_warning(const std::string& text) const { 105 std::stringstream s; 106 s<<"WARNING in instance "<<base_type::name()<<": "<<text; 107 SC_REPORT_WARNING("/OSCI_TLM-2/multi_socket", s.str().c_str()); 108 } 109 110 void display_error(const std::string& text) const { 111 std::stringstream s; 112 s<<"ERROR in instance "<<base_type::name()<<": "<<text; 113 SC_REPORT_ERROR("/OSCI_TLM-2/multi_socket", s.str().c_str()); 114 } 115 116 void check_export_binding() 117 { 118 //if our export hasn't been bound yet (due to a hierarch binding) 119 // we bind it now. 120 //We do that here as the user of the target port HAS to bind at least on callback, 121 //otherwise the socket was useless. Nevertheless, the target socket may still 122 // stay unbound afterwards. 123 if (!sc_core::sc_export<tlm::tlm_fw_transport_if<TYPES> >::get_interface()) 124 { 125 // We bind to a callback_binder that will be used as the first interface 126 // i.e. calls to the sc_export will have the same ID as calls from the first initator 127 // socket bound 128 callback_binder_fw<TYPES> * binder; 129 130 if (m_binders.size() == 0) 131 { 132 binder = new callback_binder_fw<TYPES>(m_binders.size()); 133 m_binders.push_back(binder); 134 m_export_callback_created = true; 135 } 136 else 137 { 138 binder = m_binders[0]; 139 } 140 141 sc_core::sc_export<tlm::tlm_fw_transport_if<TYPES> >::bind(*binder); 142 } 143 } 144 145 //register callback for nb transport of fw interface 146 void register_nb_transport_fw(MODULE* mod, 147 nb_cb cb) 148 { 149 check_export_binding(); 150 151 //warn if there already is a callback 152 if (!m_nb_f.empty()){ 153 display_warning("NBTransport_bw callback already registered."); 154 return; 155 } 156 157 //set the functor 158 m_nb_f.set_function(mod, cb); 159 } 160 161 //register callback for b transport of fw interface 162 void register_b_transport(MODULE* mod, 163 b_cb cb) 164 { 165 check_export_binding(); 166 167 //warn if there already is a callback 168 if (!m_b_f.empty()){ 169 display_warning("BTransport callback already registered."); 170 return; 171 } 172 173 //set the functor 174 m_b_f.set_function(mod, cb); 175 } 176 177 //register callback for debug transport of fw interface 178 void register_transport_dbg(MODULE* mod, 179 dbg_cb cb) 180 { 181 check_export_binding(); 182 183 //warn if there already is a callback 184 if (!m_dbg_f.empty()){ 185 display_warning("DebugTransport callback already registered."); 186 return; 187 } 188 189 //set the functor 190 m_dbg_f.set_function(mod, cb); 191 } 192 193 //register callback for DMI of fw interface 194 void register_get_direct_mem_ptr(MODULE* mod, 195 dmi_cb cb) 196 { 197 check_export_binding(); 198 199 //warn if there already is a callback 200 if (!m_dmi_f.empty()){ 201 display_warning("DMI callback already registered."); 202 return; 203 } 204 205 //set the functor 206 m_dmi_f.set_function(mod, cb); 207 } 208 209 210 //Override virtual functions of the tlm_target_socket: 211 // this function is called whenever an sc_port (as part of a init socket) 212 // wants to bind to the export of the underlying tlm_target_socket 213 //At this time a callback binder is created an returned to the sc_port 214 // of the init socket, so that it binds to the callback binder 215 virtual tlm::tlm_fw_transport_if<TYPES>& get_base_interface() 216 { 217 //error if this socket is already bound hierarchically 218 if (m_hierarch_bind) display_error("Socket already bound hierarchically."); 219 220 if (!m_export_callback_created) 221 m_binders.push_back(new callback_binder_fw<TYPES>(m_binders.size())); 222 else 223 m_export_callback_created = false; 224 225 return *m_binders[m_binders.size()-1]; 226 } 227 228 // const overload not allowed for multi-sockets 229 virtual const tlm::tlm_fw_transport_if<TYPES>& get_base_interface() const 230 { 231 display_error("'get_base_interface()' const not allowed for multi-sockets."); 232 return base_type::get_base_interface(); 233 } 234 235 //just return the export of the underlying tlm_target_socket in case of a hierarchical bind 236 virtual sc_core::sc_export<tlm::tlm_fw_transport_if<TYPES> >& get_base_export() 237 { 238 return *this; 239 } 240 241 //just return the export of the underlying tlm_target_socket in case of a hierarchical bind 242 virtual const sc_core::sc_export<tlm::tlm_fw_transport_if<TYPES> >& get_base_export() const 243 { 244 return base_type::get_base_export(); 245 } 246 247 //the standard end of elaboration callback 248 void end_of_elaboration(){ 249 //'break' here if the socket was told not to do callback binding 250 if (m_eoe_disabled) return; 251 252 //get the callback binders and the multi binds of the top of the hierachical bind chain 253 // NOTE: this could be the same socket if there is no hierachical bind 254 std::vector<callback_binder_fw<TYPES>* >& binders=get_hierarch_bind()->get_binders(); 255 std::map<unsigned int, tlm::tlm_bw_transport_if<TYPES>*>& multi_binds=get_hierarch_bind()->get_multi_binds(); 256 257 //iterate over all binders 258 for (unsigned int i=0; i<binders.size(); i++) { 259 binders[i]->set_callbacks(m_nb_f, m_b_f, m_dmi_f, m_dbg_f); //set the callbacks for the binder 260 if (multi_binds.find(i)!=multi_binds.end()) //check if this connection is multi-multi 261 //if so remember the interface 262 m_sockets.push_back(multi_binds[i]); 263 else{ //if we are bound to a normal socket 264 //get the calling port and try to cast it into a tlm socket base 265 base_initiator_socket_type* test=dynamic_cast<base_initiator_socket_type*>(binders[i]->get_other_side()); 266 if (!test){display_error("Not bound to tlm_socket.");} 267 m_sockets.push_back(&test->get_base_interface()); //remember the interface 268 } 269 } 270 } 271 272 // 273 // Bind multi target socket to multi target socket (hierarchical bind) 274 // 275 virtual void bind(base_type& s) 276 { 277 //warn if already bound hierarchically 278 if (m_eoe_disabled){ 279 display_warning("Socket already bound hierarchically. Bind attempt ignored."); 280 return; 281 } 282 283 //disable our own end of elaboration call 284 disable_cb_bind(); 285 286 //inform the bound target socket that it is bound hierarchically now 287 s.set_hierarch_bind((base_type*)this); 288 base_type::bind(s); //satisfy SystemC 289 } 290 291 //operator notation for hierarchical bind 292 void operator() (base_type& s) 293 { 294 bind(s); 295 } 296 297 //get access to sub port 298 tlm::tlm_bw_transport_if<TYPES>* operator[](int i){return m_sockets[i];} 299 300 //get number of bound initiators 301 // NOTE: this is only valid at end of elaboration! 302 unsigned int size(){return get_hierarch_bind()->get_binders().size();} 303 304protected: 305 //implementation of base class interface 306 base_type* get_hierarch_bind(){if (m_hierarch_bind) return m_hierarch_bind->get_hierarch_bind(); else return this;} 307 std::map<unsigned int, tlm::tlm_bw_transport_if<TYPES>*>& get_multi_binds(){return m_multi_binds;} 308 void set_hierarch_bind(base_type* h){m_hierarch_bind=h;} 309 tlm::tlm_fw_transport_if<TYPES>* get_last_binder(tlm::tlm_bw_transport_if<TYPES>* other){ 310 m_multi_binds[m_binders.size()-1]=other; 311 return m_binders[m_binders.size()-1]; 312 } 313 314 //map that stores to which index a multi init socket is connected 315 // and the interface of the multi init socket 316 std::map<unsigned int, tlm::tlm_bw_transport_if<TYPES>*> m_multi_binds; 317 318 void disable_cb_bind(){ m_eoe_disabled=true;} 319 std::vector<callback_binder_fw<TYPES>* >& get_binders(){return m_binders;} 320 //vector of connected sockets 321 std::vector<tlm::tlm_bw_transport_if<TYPES>*> m_sockets; 322 //vector of binders that convert untagged interface into tagged interface 323 std::vector<callback_binder_fw<TYPES>*> m_binders; 324 325 base_type* m_hierarch_bind; //pointer to hierarchical bound multi port 326 bool m_eoe_disabled; //bool that diables callback bindings at end of elaboration 327 bool m_export_callback_created; // bool to indicate that a callback has already been created for export binding 328 329 //callbacks as functors 330 // (allows to pass the callback to another socket that does not know the type of the module that owns 331 // the callbacks) 332 typename callback_binder_fw<TYPES>::nb_func_type m_nb_f; 333 typename callback_binder_fw<TYPES>::b_func_type m_b_f; 334 typename callback_binder_fw<TYPES>::debug_func_type m_dbg_f; 335 typename callback_binder_fw<TYPES>::dmi_func_type m_dmi_f; 336}; 337 338} 339 340#endif 341