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