1 /*****************************************************************************
2 
3   Licensed to Accellera Systems Initiative Inc. (Accellera) under one or
4   more contributor license agreements.  See the NOTICE file distributed
5   with this work for additional information regarding copyright ownership.
6   Accellera licenses this file to you under the Apache License, Version 2.0
7   (the "License"); you may not use this file except in compliance with the
8   License.  You may obtain a copy of the License at
9 
10     http://www.apache.org/licenses/LICENSE-2.0
11 
12   Unless required by applicable law or agreed to in writing, software
13   distributed under the License is distributed on an "AS IS" BASIS,
14   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
15   implied.  See the License for the specific language governing
16   permissions and limitations under the License.
17 
18  *****************************************************************************/
19 
20 #ifndef TLM_UTILS_PASSTHROUGH_TARGET_SOCKET_H_INCLUDED_
21 #define TLM_UTILS_PASSTHROUGH_TARGET_SOCKET_H_INCLUDED_
22 
23 #include <tlm>
24 #include "tlm_utils/convenience_socket_bases.h"
25 
26 namespace tlm_utils {
27 
28 template< typename MODULE, unsigned int BUSWIDTH, typename TYPES
29         , sc_core::sc_port_policy POL = sc_core::SC_ONE_OR_MORE_BOUND >
30 class passthrough_target_socket_b
31   : public tlm::tlm_target_socket<BUSWIDTH, TYPES, 1, POL>
32   , protected passthrough_socket_base
33 {
34 public:
35   typedef typename TYPES::tlm_payload_type              transaction_type;
36   typedef typename TYPES::tlm_phase_type                phase_type;
37   typedef tlm::tlm_sync_enum                            sync_enum_type;
38   typedef tlm::tlm_fw_transport_if<TYPES>               fw_interface_type;
39   typedef tlm::tlm_bw_transport_if<TYPES>               bw_interface_type;
40   typedef tlm::tlm_target_socket<BUSWIDTH,TYPES,1,POL>  base_type;
41 
42 public:
default_name()43   static const char* default_name()
44     { return sc_core::sc_gen_unique_name("passthrough_target_socket"); }
45 
46   explicit passthrough_target_socket_b(const char* n = default_name())
base_type(n)47     : base_type(n)
48     , m_process(this)
49   {
50     bind(m_process);
51   }
52 
53   using base_type::bind;
54 
55   // REGISTER_XXX
register_nb_transport_fw(MODULE * mod,sync_enum_type (MODULE::* cb)(transaction_type &,phase_type &,sc_core::sc_time &))56   void register_nb_transport_fw(MODULE* mod,
57                                 sync_enum_type (MODULE::*cb)(transaction_type&,
58                                                              phase_type&,
59                                                              sc_core::sc_time&))
60   {
61     m_process.set_nb_transport_ptr(mod, cb);
62   }
63 
register_b_transport(MODULE * mod,void (MODULE::* cb)(transaction_type &,sc_core::sc_time &))64   void register_b_transport(MODULE* mod,
65                             void (MODULE::*cb)(transaction_type&,
66                                                sc_core::sc_time&))
67   {
68     m_process.set_b_transport_ptr(mod, cb);
69   }
70 
register_transport_dbg(MODULE * mod,unsigned int (MODULE::* cb)(transaction_type &))71   void register_transport_dbg(MODULE* mod,
72                               unsigned int (MODULE::*cb)(transaction_type&))
73   {
74     m_process.set_transport_dbg_ptr(mod, cb);
75   }
76 
register_get_direct_mem_ptr(MODULE * mod,bool (MODULE::* cb)(transaction_type &,tlm::tlm_dmi &))77   void register_get_direct_mem_ptr(MODULE* mod,
78                                    bool (MODULE::*cb)(transaction_type&,
79                                                       tlm::tlm_dmi&))
80   {
81     m_process.set_get_direct_mem_ptr(mod, cb);
82   }
83 
84 private:
85   class process
86     : public tlm::tlm_fw_transport_if<TYPES>
87     , protected convenience_socket_cb_holder
88   {
89   public:
90     typedef sync_enum_type (MODULE::*NBTransportPtr)(transaction_type&,
91                                                      phase_type&,
92                                                      sc_core::sc_time&);
93     typedef void (MODULE::*BTransportPtr)(transaction_type&,
94                                             sc_core::sc_time&);
95     typedef unsigned int (MODULE::*TransportDbgPtr)(transaction_type&);
96     typedef bool (MODULE::*GetDirectMem_ptr)(transaction_type&,
97                                                tlm::tlm_dmi&);
98 
process(passthrough_socket_base * owner)99     explicit process(passthrough_socket_base* owner)
100       : convenience_socket_cb_holder(owner), m_mod(0)
101       , m_nb_transport_ptr(0)
102       , m_b_transport_ptr(0)
103       , m_transport_dbg_ptr(0)
104       , m_get_direct_mem_ptr(0)
105     {
106     }
107 
set_nb_transport_ptr(MODULE * mod,NBTransportPtr p)108     void set_nb_transport_ptr(MODULE* mod, NBTransportPtr p)
109     {
110       if (m_nb_transport_ptr) {
111         display_warning("non-blocking callback already registered");
112         return;
113       }
114       sc_assert(!m_mod || m_mod == mod);
115       m_mod = mod;
116       m_nb_transport_ptr = p;
117     }
118 
set_b_transport_ptr(MODULE * mod,BTransportPtr p)119     void set_b_transport_ptr(MODULE* mod, BTransportPtr p)
120     {
121       if (m_b_transport_ptr) {
122         display_warning("blocking callback already registered");
123         return;
124       }
125       sc_assert(!m_mod || m_mod == mod);
126       m_mod = mod;
127       m_b_transport_ptr = p;
128     }
129 
set_transport_dbg_ptr(MODULE * mod,TransportDbgPtr p)130     void set_transport_dbg_ptr(MODULE* mod, TransportDbgPtr p)
131     {
132       if (m_transport_dbg_ptr) {
133         display_warning("debug callback already registered");
134         return;
135       }
136       sc_assert(!m_mod || m_mod == mod);
137       m_mod = mod;
138       m_transport_dbg_ptr = p;
139     }
140 
set_get_direct_mem_ptr(MODULE * mod,GetDirectMem_ptr p)141     void set_get_direct_mem_ptr(MODULE* mod, GetDirectMem_ptr p)
142     {
143       if (m_get_direct_mem_ptr) {
144         display_warning("get DMI pointer callback already registered");
145         return;
146       }
147       sc_assert(!m_mod || m_mod == mod);
148       m_mod = mod;
149       m_get_direct_mem_ptr = p;
150     }
151 
nb_transport_fw(transaction_type & trans,phase_type & phase,sc_core::sc_time & t)152     sync_enum_type nb_transport_fw(transaction_type& trans,
153                                    phase_type& phase,
154                                    sc_core::sc_time& t)
155     {
156       if (m_nb_transport_ptr) {
157         // forward call
158         sc_assert(m_mod);
159         return (m_mod->*m_nb_transport_ptr)(trans, phase, t);
160       }
161       display_error("no non-blocking callback registered");
162       return tlm::TLM_COMPLETED;
163     }
164 
b_transport(transaction_type & trans,sc_core::sc_time & t)165     void b_transport(transaction_type& trans, sc_core::sc_time& t)
166     {
167       if (m_b_transport_ptr) {
168         // forward call
169         sc_assert(m_mod);
170         return (m_mod->*m_b_transport_ptr)(trans, t);
171       }
172       display_error("no blocking callback registered");
173     }
174 
transport_dbg(transaction_type & trans)175     unsigned int transport_dbg(transaction_type& trans)
176     {
177       if (m_transport_dbg_ptr) {
178         // forward call
179         sc_assert(m_mod);
180         return (m_mod->*m_transport_dbg_ptr)(trans);
181       }
182       // No debug support
183       return 0;
184     }
185 
get_direct_mem_ptr(transaction_type & trans,tlm::tlm_dmi & dmi_data)186     bool get_direct_mem_ptr(transaction_type& trans,
187                             tlm::tlm_dmi&  dmi_data)
188     {
189       if (m_get_direct_mem_ptr) {
190         // forward call
191         sc_assert(m_mod);
192         return (m_mod->*m_get_direct_mem_ptr)(trans, dmi_data);
193       }
194       // No DMI support
195       dmi_data.allow_read_write();
196       dmi_data.set_start_address(0x0);
197       dmi_data.set_end_address((sc_dt::uint64)-1);
198       return false;
199     }
200 
201   private:
202     MODULE* m_mod;
203     NBTransportPtr m_nb_transport_ptr;
204     BTransportPtr m_b_transport_ptr;
205     TransportDbgPtr m_transport_dbg_ptr;
206     GetDirectMem_ptr m_get_direct_mem_ptr;
207   };
208 
209 private:
get_socket()210   const sc_core::sc_object* get_socket() const { return this; }
211 private:
212   process m_process;
213 };
214 
215 template< typename MODULE, unsigned int BUSWIDTH = 32
216         , typename TYPES = tlm::tlm_base_protocol_types >
217 class passthrough_target_socket
218   : public passthrough_target_socket_b<MODULE,BUSWIDTH,TYPES>
219 {
220   typedef passthrough_target_socket_b<MODULE,BUSWIDTH,TYPES> socket_b;
221 public:
passthrough_target_socket()222   passthrough_target_socket() : socket_b() {}
passthrough_target_socket(const char * name)223   explicit passthrough_target_socket(const char* name) : socket_b(name) {}
224 };
225 
226 template< typename MODULE, unsigned int BUSWIDTH = 32
227         , typename TYPES = tlm::tlm_base_protocol_types >
228 class passthrough_target_socket_optional
229   : public passthrough_target_socket_b<MODULE,BUSWIDTH,TYPES,sc_core::SC_ZERO_OR_MORE_BOUND>
230 {
231   typedef passthrough_target_socket_b<MODULE,BUSWIDTH,TYPES,sc_core::SC_ZERO_OR_MORE_BOUND> socket_b;
232 public:
passthrough_target_socket_optional()233   passthrough_target_socket_optional() : socket_b() {}
passthrough_target_socket_optional(const char * name)234   explicit passthrough_target_socket_optional(const char* name) : socket_b(name) {}
235 };
236 
237 //ID Tagged version
238 template< typename MODULE, unsigned int BUSWIDTH, typename TYPES
239         , sc_core::sc_port_policy POL = sc_core::SC_ONE_OR_MORE_BOUND >
240 class passthrough_target_socket_tagged_b
241   : public tlm::tlm_target_socket<BUSWIDTH, TYPES, 1, POL>
242   , protected passthrough_socket_base
243 {
244 public:
245   typedef typename TYPES::tlm_payload_type              transaction_type;
246   typedef typename TYPES::tlm_phase_type                phase_type;
247   typedef tlm::tlm_sync_enum                            sync_enum_type;
248   typedef tlm::tlm_fw_transport_if<TYPES>               fw_interface_type;
249   typedef tlm::tlm_bw_transport_if<TYPES>               bw_interface_type;
250   typedef tlm::tlm_target_socket<BUSWIDTH,TYPES,1,POL>  base_type;
251 
default_name()252   static const char* default_name()
253     { return sc_core::sc_gen_unique_name("passthrough_target_socket_tagged"); }
254 
255 public:
256   explicit passthrough_target_socket_tagged_b(const char* n = default_name())
base_type(n)257     : base_type(n)
258     , m_process(this)
259   {
260     bind(m_process);
261   }
262 
263   using base_type::bind;
264 
265   // REGISTER_XXX
register_nb_transport_fw(MODULE * mod,sync_enum_type (MODULE::* cb)(int id,transaction_type &,phase_type &,sc_core::sc_time &),int id)266   void register_nb_transport_fw(MODULE* mod,
267                                 sync_enum_type (MODULE::*cb)(int id,
268                                                              transaction_type&,
269                                                              phase_type&,
270                                                              sc_core::sc_time&),
271                                 int id)
272   {
273     m_process.set_nb_transport_ptr(mod, cb);
274     m_process.set_nb_transport_user_id(id);
275   }
276 
register_b_transport(MODULE * mod,void (MODULE::* cb)(int id,transaction_type &,sc_core::sc_time &),int id)277   void register_b_transport(MODULE* mod,
278                             void (MODULE::*cb)(int id,
279                                                transaction_type&,
280                                                sc_core::sc_time&),
281                             int id)
282   {
283     m_process.set_b_transport_ptr(mod, cb);
284     m_process.set_b_transport_user_id(id);
285   }
286 
register_transport_dbg(MODULE * mod,unsigned int (MODULE::* cb)(int id,transaction_type &),int id)287   void register_transport_dbg(MODULE* mod,
288                               unsigned int (MODULE::*cb)(int id,
289                                                          transaction_type&),
290                               int id)
291   {
292     m_process.set_transport_dbg_ptr(mod, cb);
293     m_process.set_transport_dbg_user_id(id);
294   }
295 
register_get_direct_mem_ptr(MODULE * mod,bool (MODULE::* cb)(int id,transaction_type &,tlm::tlm_dmi &),int id)296   void register_get_direct_mem_ptr(MODULE* mod,
297                                    bool (MODULE::*cb)(int id,
298                                                       transaction_type&,
299                                                       tlm::tlm_dmi&),
300                                    int id)
301   {
302     m_process.set_get_direct_mem_ptr(mod, cb);
303     m_process.set_get_dmi_user_id(id);
304   }
305 
306 private:
307   class process
308     : public tlm::tlm_fw_transport_if<TYPES>
309     , protected convenience_socket_cb_holder
310   {
311   public:
312     typedef sync_enum_type (MODULE::*NBTransportPtr)(int id,
313                                                      transaction_type&,
314                                                      phase_type&,
315                                                      sc_core::sc_time&);
316     typedef void (MODULE::*BTransportPtr)(int id,
317                                           transaction_type&,
318                                           sc_core::sc_time&);
319     typedef unsigned int (MODULE::*TransportDbgPtr)(int id,
320                                                     transaction_type&);
321     typedef bool (MODULE::*GetDirectMem_ptr)(int id,
322                                              transaction_type&,
323                                              tlm::tlm_dmi&);
324 
process(passthrough_socket_base * owner)325     process(passthrough_socket_base* owner)
326       : convenience_socket_cb_holder(owner), m_mod(0)
327       , m_nb_transport_ptr(0)
328       , m_b_transport_ptr(0)
329       , m_transport_dbg_ptr(0)
330       , m_get_direct_mem_ptr(0)
331       , m_nb_transport_user_id(0)
332       , m_b_transport_user_id(0)
333       , m_transport_dbg_user_id(0)
334       , m_get_dmi_user_id(0)
335     {
336     }
337 
set_nb_transport_user_id(int id)338     void set_nb_transport_user_id(int id) { m_nb_transport_user_id = id; }
set_b_transport_user_id(int id)339     void set_b_transport_user_id(int id) { m_b_transport_user_id = id; }
set_transport_dbg_user_id(int id)340     void set_transport_dbg_user_id(int id) { m_transport_dbg_user_id = id; }
set_get_dmi_user_id(int id)341     void set_get_dmi_user_id(int id) { m_get_dmi_user_id = id; }
342 
set_nb_transport_ptr(MODULE * mod,NBTransportPtr p)343     void set_nb_transport_ptr(MODULE* mod, NBTransportPtr p)
344     {
345       if (m_nb_transport_ptr) {
346         display_warning("non-blocking callback already registered");
347         return;
348       }
349       sc_assert(!m_mod || m_mod == mod);
350       m_mod = mod;
351       m_nb_transport_ptr = p;
352     }
353 
set_b_transport_ptr(MODULE * mod,BTransportPtr p)354     void set_b_transport_ptr(MODULE* mod, BTransportPtr p)
355     {
356       if (m_b_transport_ptr) {
357         display_warning("blocking callback already registered");
358         return;
359       }
360       sc_assert(!m_mod || m_mod == mod);
361       m_mod = mod;
362       m_b_transport_ptr = p;
363     }
364 
set_transport_dbg_ptr(MODULE * mod,TransportDbgPtr p)365     void set_transport_dbg_ptr(MODULE* mod, TransportDbgPtr p)
366     {
367       if (m_transport_dbg_ptr) {
368         display_warning("debug callback already registered");
369         return;
370       }
371       sc_assert(!m_mod || m_mod == mod);
372       m_mod = mod;
373       m_transport_dbg_ptr = p;
374     }
375 
set_get_direct_mem_ptr(MODULE * mod,GetDirectMem_ptr p)376     void set_get_direct_mem_ptr(MODULE* mod, GetDirectMem_ptr p)
377     {
378       if (m_get_direct_mem_ptr) {
379         display_warning("get DMI pointer callback already registered");
380         return;
381       }
382       sc_assert(!m_mod || m_mod == mod);
383       m_mod = mod;
384       m_get_direct_mem_ptr = p;
385     }
386 
nb_transport_fw(transaction_type & trans,phase_type & phase,sc_core::sc_time & t)387     sync_enum_type nb_transport_fw(transaction_type& trans,
388                                    phase_type& phase,
389                                    sc_core::sc_time& t)
390     {
391       if (m_nb_transport_ptr) {
392         // forward call
393         sc_assert(m_mod);
394         return (m_mod->*m_nb_transport_ptr)(m_nb_transport_user_id, trans, phase, t);
395       }
396       display_error("no non-blocking callback registered");
397       return tlm::TLM_COMPLETED;
398     }
399 
b_transport(transaction_type & trans,sc_core::sc_time & t)400     void b_transport(transaction_type& trans, sc_core::sc_time& t)
401     {
402       if (m_b_transport_ptr) {
403         // forward call
404         sc_assert(m_mod);
405         return (m_mod->*m_b_transport_ptr)(m_b_transport_user_id, trans, t);
406       }
407       display_error("no blocking callback registered");
408     }
409 
transport_dbg(transaction_type & trans)410     unsigned int transport_dbg(transaction_type& trans)
411     {
412       if (m_transport_dbg_ptr) {
413         // forward call
414         sc_assert(m_mod);
415         return (m_mod->*m_transport_dbg_ptr)(m_transport_dbg_user_id, trans);
416       }
417       // No debug support
418       return 0;
419     }
420 
get_direct_mem_ptr(transaction_type & trans,tlm::tlm_dmi & dmi_data)421     bool get_direct_mem_ptr(transaction_type& trans,
422                             tlm::tlm_dmi&  dmi_data)
423     {
424       if (m_get_direct_mem_ptr) {
425         // forward call
426         sc_assert(m_mod);
427         return (m_mod->*m_get_direct_mem_ptr)(m_get_dmi_user_id, trans, dmi_data);
428       }
429       // No DMI support
430       dmi_data.allow_read_write();
431       dmi_data.set_start_address(0x0);
432       dmi_data.set_end_address((sc_dt::uint64)-1);
433       return false;
434     }
435 
436   private:
437     MODULE* m_mod;
438     NBTransportPtr m_nb_transport_ptr;
439     BTransportPtr m_b_transport_ptr;
440     TransportDbgPtr m_transport_dbg_ptr;
441     GetDirectMem_ptr m_get_direct_mem_ptr;
442     int m_nb_transport_user_id;
443     int m_b_transport_user_id;
444     int m_transport_dbg_user_id;
445     int m_get_dmi_user_id;
446   };
447 
448 private:
get_socket()449   const sc_core::sc_object* get_socket() const { return this; }
450 private:
451   process m_process;
452 };
453 
454 template< typename MODULE, unsigned int BUSWIDTH = 32
455         , typename TYPES = tlm::tlm_base_protocol_types >
456 class passthrough_target_socket_tagged
457   : public passthrough_target_socket_tagged_b<MODULE,BUSWIDTH,TYPES>
458 {
459   typedef passthrough_target_socket_tagged_b<MODULE,BUSWIDTH,TYPES> socket_b;
460 public:
passthrough_target_socket_tagged()461   passthrough_target_socket_tagged() : socket_b() {}
passthrough_target_socket_tagged(const char * name)462   explicit passthrough_target_socket_tagged(const char* name) : socket_b(name) {}
463 };
464 
465 template< typename MODULE, unsigned int BUSWIDTH = 32
466         , typename TYPES = tlm::tlm_base_protocol_types >
467 class passthrough_target_socket_tagged_optional
468   : public passthrough_target_socket_tagged_b<MODULE,BUSWIDTH,TYPES,sc_core::SC_ZERO_OR_MORE_BOUND>
469 {
470   typedef passthrough_target_socket_tagged_b<MODULE,BUSWIDTH,TYPES,sc_core::SC_ZERO_OR_MORE_BOUND> socket_b;
471 public:
passthrough_target_socket_tagged_optional()472   passthrough_target_socket_tagged_optional() : socket_b() {}
passthrough_target_socket_tagged_optional(const char * name)473   explicit passthrough_target_socket_tagged_optional(const char* name) : socket_b(name) {}
474 };
475 
476 } // namespace tlm_utils
477 #endif // TLM_UTILS_PASSTHROUGH_TARGET_SOCKET_H_INCLUDED_
478