multi_passthrough_sockets_bug.cpp revision 12855:588919e0e4aa
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#define SC_INCLUDE_DYNAMIC_PROCESSES
20#include "systemc"
21#include "tlm"
22#include "tlm_utils/simple_initiator_socket.h"
23#include "tlm_utils/multi_passthrough_target_socket.h"
24
25class introspection_extension;
26
27class initiator_module : public sc_core::sc_module
28{
29public:
30
31  tlm_utils::simple_initiator_socket<initiator_module> initiator_socket;
32  SC_HAS_PROCESS(initiator_module);
33  explicit initiator_module(sc_core::sc_module_name module_name)
34    : sc_core::sc_module(module_name)
35    , initiator_socket("initiator_socket")
36  {
37    SC_THREAD(process);
38  }
39
40  void process()
41  {
42    // To verify regular TLM-2 access from initiators are OK
43    tlm::tlm_generic_payload transaction;
44
45    unsigned char byte = 0x42;
46
47    transaction.set_command(tlm::TLM_WRITE_COMMAND);
48    transaction.set_address(sc_dt::uint64(0));
49    transaction.set_data_length(1);
50    transaction.set_streaming_width(1);
51    transaction.set_data_ptr(&byte);
52    transaction.set_byte_enable_ptr(0);
53    transaction.set_byte_enable_length(0);
54    transaction.set_dmi_allowed(false);
55    transaction.set_response_status(tlm::TLM_INCOMPLETE_RESPONSE);
56
57    sc_core::sc_time t = sc_core::SC_ZERO_TIME;
58
59    initiator_socket->b_transport(transaction, t);
60  }
61
62};
63
64class target_module : public sc_core::sc_module
65{
66public:
67
68  tlm_utils::multi_passthrough_target_socket<target_module> target_socket;
69  tlm_utils::multi_passthrough_target_socket<target_module, 32, tlm::tlm_base_protocol_types,0,::sc_core::SC_ZERO_OR_MORE_BOUND> target_optional;
70
71  explicit target_module(sc_core::sc_module_name module_name)
72    : sc_core::sc_module(module_name)
73    , target_socket("target_socket")
74    , target_optional("target_optional")
75  {
76    target_socket.register_b_transport(this, &target_module::transport);
77    target_socket.register_transport_dbg(this, &target_module::transport_dbg);
78    target_socket.register_get_direct_mem_ptr(this, &target_module::get_direct_mem_ptr);
79
80    // bind callbacks to optional socket (unbound)
81    target_optional.register_b_transport(this, &target_module::transport);
82    target_optional.register_transport_dbg(this, &target_module::transport_dbg);
83    target_optional.register_get_direct_mem_ptr(this, &target_module::get_direct_mem_ptr);
84  }
85
86  virtual void transport(int port, tlm::tlm_generic_payload & transaction, sc_core::sc_time & t) {}
87
88  virtual unsigned int transport_dbg(int port, tlm::tlm_generic_payload & transaction)
89  {
90    if ((transaction.get_command() == tlm::TLM_IGNORE_COMMAND) &&
91        transaction.get_extension<introspection_extension>())
92    {
93      std::cout << "Received successfully introspection extension!" << std::endl;
94    }
95
96    return 0;
97  }
98
99  virtual bool get_direct_mem_ptr(int port, tlm::tlm_generic_payload & transaction, tlm::tlm_dmi & dmi_data) { return false; }
100
101};
102
103// Simple empty extension to verify the target module is receiving it
104class introspection_extension : public tlm::tlm_extension<introspection_extension>
105{
106public:
107
108  virtual tlm_extension_base * clone() const
109  {
110    return new introspection_extension;
111  }
112
113  virtual void copy_from(tlm_extension_base const & ext)
114  {
115  }
116
117};
118
119class introspector_module : public sc_core::sc_module
120{
121public:
122
123  SC_HAS_PROCESS(introspector_module);
124  introspector_module(sc_core::sc_module_name module_name) :
125    sc_core::sc_module(module_name)
126  {
127    SC_THREAD(process);
128  }
129
130  void send_introspection_request(sc_core::sc_export<tlm::tlm_fw_transport_if<> > & target_socket)
131  {
132    tlm::tlm_generic_payload transaction;
133
134    transaction.set_command(tlm::TLM_IGNORE_COMMAND);
135    transaction.set_address(sc_dt::uint64(0));
136    transaction.set_data_length(0);
137    transaction.set_streaming_width(0);
138    transaction.set_data_ptr(0);
139    transaction.set_byte_enable_ptr(0);
140    transaction.set_byte_enable_length(0);
141    transaction.set_dmi_allowed(false);
142    transaction.set_response_status(tlm::TLM_INCOMPLETE_RESPONSE);
143
144    introspection_extension *ext = new introspection_extension;
145
146    transaction.set_extension(ext);
147
148    target_socket->transport_dbg(transaction);
149  }
150
151  void find_target_sockets(sc_core::sc_module *module)
152  {
153    std::vector<sc_core::sc_object*> children = module->get_child_objects();
154
155    for (std::vector<sc_core::sc_object*>::iterator i = children.begin(); i != children.end(); ++i)
156    {
157      if (dynamic_cast<sc_core::sc_module *>(*i))
158      {
159        find_target_sockets(dynamic_cast<sc_core::sc_module *>(*i));
160      }
161      else if (dynamic_cast<sc_core::sc_export<tlm::tlm_fw_transport_if<> > *>((*i)))
162      {
163        sc_core::sc_export<tlm::tlm_fw_transport_if<> > * target_socket = dynamic_cast<sc_core::sc_export<tlm::tlm_fw_transport_if<> > *>(*i);
164
165        send_introspection_request(*target_socket);
166      }
167    }
168  }
169
170  void process()
171  {
172    const std::vector<sc_core::sc_object*> & top_objs = sc_core::sc_get_top_level_objects();
173
174    for (std::vector<sc_core::sc_object*>::const_iterator i = top_objs.begin(); i != top_objs.end(); ++i)
175    {
176      if (dynamic_cast<sc_core::sc_module *>(*i))
177      {
178        find_target_sockets(dynamic_cast<sc_core::sc_module *>(*i));
179      }
180    }
181  }
182
183};
184
185int sc_main(int argc, char* argv[])
186{
187  initiator_module    initiator("initiator");
188  target_module       target("target");
189  introspector_module introspector("introspector");
190
191  initiator.initiator_socket(target.target_socket);
192
193  sc_core::sc_start();
194
195  return 0;
196}
197