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 __SIMPLE_INITIATOR_SOCKET_H__
21#define __SIMPLE_INITIATOR_SOCKET_H__
22
23#include <tlm>
24#include <sstream>
25
26namespace tlm_utils {
27
28template <typename MODULE,
29          unsigned int BUSWIDTH = 32,
30          typename TYPES = tlm::tlm_base_protocol_types>
31class simple_initiator_socket :
32  public tlm::tlm_initiator_socket<BUSWIDTH, TYPES>
33{
34public:
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_initiator_socket<BUSWIDTH, TYPES>    base_type;
41
42public:
43  simple_initiator_socket() :
44    base_type(sc_core::sc_gen_unique_name("simple_initiator_socket")),
45    m_process(this->name())
46  {
47    this->m_export.bind(m_process);
48  }
49
50  explicit simple_initiator_socket(const char* n) :
51    base_type(n),
52    m_process(this->name())
53  {
54    this->m_export.bind(m_process);
55  }
56
57  void register_nb_transport_bw(MODULE* mod,
58                                sync_enum_type (MODULE::*cb)(transaction_type&,
59                                                             phase_type&,
60                                                             sc_core::sc_time&))
61  {
62    m_process.set_transport_ptr(mod, cb);
63  }
64
65  void register_invalidate_direct_mem_ptr(MODULE* mod,
66                                          void (MODULE::*cb)(sc_dt::uint64, sc_dt::uint64))
67  {
68    m_process.set_invalidate_direct_mem_ptr(mod, cb);
69  }
70
71private:
72  class process : public tlm::tlm_bw_transport_if<TYPES>
73  {
74  public:
75    typedef sync_enum_type (MODULE::*TransportPtr)(transaction_type&,
76                                                   phase_type&,
77                                                   sc_core::sc_time&);
78    typedef void (MODULE::*InvalidateDirectMemPtr)(sc_dt::uint64,
79                                                   sc_dt::uint64);
80
81    process(const std::string& name) :
82      m_name(name),
83      m_mod(0),
84      m_transport_ptr(0),
85      m_invalidate_direct_mem_ptr(0)
86    {
87    }
88
89    void set_transport_ptr(MODULE* mod, TransportPtr p)
90    {
91      if (m_transport_ptr) {
92        std::stringstream s;
93        s << m_name << ": non-blocking callback allready registered";
94        SC_REPORT_WARNING("/OSCI_TLM-2/simple_socket",s.str().c_str());
95      } else {
96        assert(!m_mod || m_mod == mod);
97        m_mod = mod;
98        m_transport_ptr = p;
99      }
100    }
101
102    void set_invalidate_direct_mem_ptr(MODULE* mod, InvalidateDirectMemPtr p)
103    {
104      if (m_invalidate_direct_mem_ptr) {
105        std::stringstream s;
106        s << m_name << ": invalidate DMI callback allready registered";
107        SC_REPORT_WARNING("/OSCI_TLM-2/simple_socket",s.str().c_str());
108      } else {
109        assert(!m_mod || m_mod == mod);
110        m_mod = mod;
111        m_invalidate_direct_mem_ptr = p;
112      }
113    }
114
115    sync_enum_type nb_transport_bw(transaction_type& trans, phase_type& phase, sc_core::sc_time& t)
116    {
117      if (m_transport_ptr) {
118        // forward call
119        assert(m_mod);
120        return (m_mod->*m_transport_ptr)(trans, phase, t);
121
122      } else {
123        std::stringstream s;
124        s << m_name << ": no transport callback registered";
125        SC_REPORT_ERROR("/OSCI_TLM-2/simple_socket",s.str().c_str());
126      }
127      return tlm::TLM_ACCEPTED;   ///< unreachable code
128    }
129
130    void invalidate_direct_mem_ptr(sc_dt::uint64 start_range,
131                                   sc_dt::uint64 end_range)
132    {
133      if (m_invalidate_direct_mem_ptr) {
134        // forward call
135        assert(m_mod);
136        (m_mod->*m_invalidate_direct_mem_ptr)(start_range, end_range);
137      }
138    }
139
140  private:
141    const std::string m_name;
142    MODULE* m_mod;
143    TransportPtr m_transport_ptr;
144    InvalidateDirectMemPtr m_invalidate_direct_mem_ptr;
145  };
146
147private:
148  process m_process;
149};
150
151// Tagged version
152
153template <typename MODULE,
154          unsigned int BUSWIDTH = 32,
155          typename TYPES = tlm::tlm_base_protocol_types>
156class simple_initiator_socket_tagged :
157  public tlm::tlm_initiator_socket<BUSWIDTH, TYPES>
158{
159public:
160  typedef typename TYPES::tlm_payload_type              transaction_type;
161  typedef typename TYPES::tlm_phase_type                phase_type;
162  typedef tlm::tlm_sync_enum                            sync_enum_type;
163  typedef tlm::tlm_fw_transport_if<TYPES>               fw_interface_type;
164  typedef tlm::tlm_bw_transport_if<TYPES>               bw_interface_type;
165  typedef tlm::tlm_initiator_socket<BUSWIDTH, TYPES>    base_type;
166
167public:
168  simple_initiator_socket_tagged() :
169    base_type(sc_core::sc_gen_unique_name("simple_initiator_socket_tagged")),
170    m_process(this->name())
171  {
172    this->m_export.bind(m_process);
173  }
174
175  explicit simple_initiator_socket_tagged(const char* n) :
176    base_type(n),
177    m_process(this->name())
178  {
179    this->m_export.bind(m_process);
180  }
181
182  void register_nb_transport_bw(MODULE* mod,
183                                sync_enum_type (MODULE::*cb)(int,
184                                                             transaction_type&,
185                                                             phase_type&,
186                                                             sc_core::sc_time&),
187                                int id)
188  {
189    m_process.set_transport_ptr(mod, cb);
190    m_process.set_transport_user_id(id);
191  }
192
193  void register_invalidate_direct_mem_ptr(MODULE* mod,
194                                          void (MODULE::*cb)(int, sc_dt::uint64, sc_dt::uint64),
195                                           int id)
196  {
197    m_process.set_invalidate_direct_mem_ptr(mod, cb);
198    m_process.set_invalidate_dmi_user_id(id);
199  }
200
201private:
202  class process : public tlm::tlm_bw_transport_if<TYPES>
203  {
204  public:
205    typedef sync_enum_type (MODULE::*TransportPtr)(int,
206                                                   transaction_type&,
207                                                   phase_type&,
208                                                   sc_core::sc_time&);
209    typedef void (MODULE::*InvalidateDirectMemPtr)(int,
210                                                   sc_dt::uint64,
211                                                   sc_dt::uint64);
212
213    process(const std::string& name) :
214      m_name(name),
215      m_mod(0),
216      m_transport_ptr(0),
217      m_invalidate_direct_mem_ptr(0),
218      m_transport_user_id(0),
219      m_invalidate_direct_mem_user_id(0)
220    {
221    }
222
223    void set_transport_user_id(int id) { m_transport_user_id = id; }
224    void set_invalidate_dmi_user_id(int id) { m_invalidate_direct_mem_user_id = id; }
225
226    void set_transport_ptr(MODULE* mod, TransportPtr p)
227    {
228      if (m_transport_ptr) {
229        std::stringstream s;
230        s << m_name << ": non-blocking callback allready registered";
231        SC_REPORT_WARNING("/OSCI_TLM-2/simple_socket",s.str().c_str());
232      } else {
233        assert(!m_mod || m_mod == mod);
234        m_mod = mod;
235        m_transport_ptr = p;
236      }
237    }
238
239    void set_invalidate_direct_mem_ptr(MODULE* mod, InvalidateDirectMemPtr p)
240    {
241      if (m_invalidate_direct_mem_ptr) {
242        std::stringstream s;
243        s << m_name << ": invalidate DMI callback allready registered";
244        SC_REPORT_WARNING("/OSCI_TLM-2/simple_socket",s.str().c_str());
245      } else {
246        assert(!m_mod || m_mod == mod);
247        m_mod = mod;
248        m_invalidate_direct_mem_ptr = p;
249      }
250    }
251
252    sync_enum_type nb_transport_bw(transaction_type& trans, phase_type& phase, sc_core::sc_time& t)
253    {
254      if (m_transport_ptr) {
255        // forward call
256        assert(m_mod);
257        return (m_mod->*m_transport_ptr)(m_transport_user_id, trans, phase, t);
258
259      } else {
260        std::stringstream s;
261        s << m_name << ": no transport callback registered";
262        SC_REPORT_ERROR("/OSCI_TLM-2/simple_socket",s.str().c_str());
263      }
264      return tlm::TLM_ACCEPTED;   ///< unreachable code
265    }
266
267    void invalidate_direct_mem_ptr(sc_dt::uint64 start_range,
268                                   sc_dt::uint64 end_range)
269    {
270      if (m_invalidate_direct_mem_ptr) {
271        // forward call
272        assert(m_mod);
273        (m_mod->*m_invalidate_direct_mem_ptr)(m_invalidate_direct_mem_user_id, start_range, end_range);
274      }
275    }
276
277  private:
278    const std::string m_name;
279    MODULE* m_mod;
280    TransportPtr m_transport_ptr;
281    InvalidateDirectMemPtr m_invalidate_direct_mem_ptr;
282    int m_transport_user_id;
283    int m_invalidate_direct_mem_user_id;
284  };
285
286private:
287  process m_process;
288};
289
290}
291
292#endif
293