gem5  v20.0.0.3
SimpleBusAT.h
Go to the documentation of this file.
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 __SIMPLEBUSAT_H__
21 #define __SIMPLEBUSAT_H__
22 
23 //#include <systemc>
24 #include "tlm.h"
25 
26 #include "tlm_utils/simple_target_socket.h"
27 #include "tlm_utils/simple_initiator_socket.h"
28 
29 #include "tlm_utils/peq_with_get.h"
30 
31 template <int NR_OF_INITIATORS, int NR_OF_TARGETS>
33 {
34 public:
40 
41 public:
42  target_socket_type target_socket[NR_OF_INITIATORS];
43  initiator_socket_type initiator_socket[NR_OF_TARGETS];
44 
45 public:
48  sc_core::sc_module(name),
49  mRequestPEQ("requestPEQ"),
50  mResponsePEQ("responsePEQ")
51  {
52  for (unsigned int i = 0; i < NR_OF_INITIATORS; ++i) {
54  target_socket[i].register_transport_dbg(this, &SimpleBusAT::transportDebug, i);
56  }
57  for (unsigned int i = 0; i < NR_OF_TARGETS; ++i) {
60  }
61 
64  }
65 
66  //
67  // Dummy decoder:
68  // - address[31-28]: portId
69  // - address[27-0]: masked address
70  //
71 
72  unsigned int getPortId(const sc_dt::uint64& address)
73  {
74  return (unsigned int)address >> 28;
75  }
76 
77  sc_dt::uint64 getAddressOffset(unsigned int portId)
78  {
79  return portId << 28;
80  }
81 
82  sc_dt::uint64 getAddressMask(unsigned int portId)
83  {
84  return 0xfffffff;
85  }
86 
87  unsigned int decode(const sc_dt::uint64& address)
88  {
89  // decode address:
90  // - return initiator socket id
91 
92  return getPortId(address);
93  }
94 
95  //
96  // AT protocol
97  //
98 
100  {
101  while (true) {
103 
104  transaction_type* trans;
105  while ((trans = mRequestPEQ.get_next_transaction())!=0) {
106  unsigned int portId = decode(trans->get_address());
107  assert(portId < NR_OF_TARGETS);
108  initiator_socket_type* decodeSocket = &initiator_socket[portId];
109  trans->set_address(trans->get_address() & getAddressMask(portId));
110 
111  // Fill in the destination port
113  assert(it != mPendingTransactions.end());
114  it->second.to = decodeSocket;
115 
116  phase_type phase = tlm::BEGIN_REQ;
118 
119  // FIXME: No limitation on number of pending transactions
120  // All targets (that return false) must support multiple transactions
121  switch ((*decodeSocket)->nb_transport_fw(*trans, phase, t)) {
122  case tlm::TLM_ACCEPTED:
123  case tlm::TLM_UPDATED:
124  // Transaction not yet finished
125  if (phase == tlm::BEGIN_REQ) {
126  // Request phase not yet finished
128 
129  } else if (phase == tlm::END_REQ) {
130  // Request phase finished, but response phase not yet started
131  wait(t);
132 
133  } else if (phase == tlm::BEGIN_RESP) {
134  mResponsePEQ.notify(*trans, t);
135  // Not needed to send END_REQ to initiator
136  continue;
137 
138  } else { // END_RESP
139  assert(0); exit(1);
140  }
141 
142  // only send END_REQ to initiator if BEGIN_RESP was not already send
143  if (it->second.from) {
144  phase = tlm::END_REQ;
146  (*it->second.from)->nb_transport_bw(*trans, phase, t);
147  }
148 
149  break;
150 
151  case tlm::TLM_COMPLETED:
152  // Transaction finished
153  mResponsePEQ.notify(*trans, t);
154 
155  // reset to destination port (we must not send END_RESP to target)
156  it->second.to = 0;
157 
158  wait(t);
159  break;
160 
161  default:
162  assert(0); exit(1);
163  };
164  }
165  }
166  }
167 
169  {
170  while (true) {
172 
173  transaction_type* trans;
174  while ((trans = mResponsePEQ.get_next_transaction())!=0) {
176  assert(it != mPendingTransactions.end());
177 
178  phase_type phase = tlm::BEGIN_RESP;
180 
181  target_socket_type* initiatorSocket = it->second.from;
182  // if BEGIN_RESP is send first we don't have to send END_REQ anymore
183  it->second.from = 0;
184 
185  switch ((*initiatorSocket)->nb_transport_bw(*trans, phase, t)) {
186  case tlm::TLM_COMPLETED:
187  // Transaction finished
188  wait(t);
189  break;
190 
191  case tlm::TLM_ACCEPTED:
192  case tlm::TLM_UPDATED:
193  // Transaction not yet finished
195  break;
196 
197  default:
198  assert(0); exit(1);
199  };
200 
201  // forward END_RESP to target
202  if (it->second.to) {
203  phase = tlm::END_RESP;
205  #if ( ! NDEBUG )
206  sync_enum_type r = (*it->second.to)->nb_transport_fw(*trans, phase, t);
207  #endif /* ! NDEBUG */
208  assert(r == tlm::TLM_COMPLETED);
209  }
210 
211  mPendingTransactions.erase(it);
212  trans->release();
213  }
214  }
215  }
216 
217  //
218  // interface methods
219  //
220 
221  sync_enum_type initiatorNBTransport(int initiator_id,
222  transaction_type& trans,
223  phase_type& phase,
225  {
226  if (phase == tlm::BEGIN_REQ) {
227  trans.acquire();
228  addPendingTransaction(trans, 0, initiator_id);
229 
230  mRequestPEQ.notify(trans, t);
231 
232  } else if (phase == tlm::END_RESP) {
234  return tlm::TLM_COMPLETED;
235 
236  } else {
237  std::cout << "ERROR: '" << name()
238  << "': Illegal phase received from initiator." << std::endl;
239  assert(false); exit(1);
240  }
241 
242  return tlm::TLM_ACCEPTED;
243  }
244 
245  sync_enum_type targetNBTransport(int portId,
246  transaction_type& trans,
247  phase_type& phase,
249  {
250  if (phase != tlm::END_REQ && phase != tlm::BEGIN_RESP) {
251  std::cout << "ERROR: '" << name()
252  << "': Illegal phase received from target." << std::endl;
253  assert(false); exit(1);
254  }
255 
257  if (phase == tlm::BEGIN_RESP) {
258  mResponsePEQ.notify(trans, t);
259  }
260 
261  return tlm::TLM_ACCEPTED;
262  }
263 
264  unsigned int transportDebug(int initiator_id, transaction_type& trans)
265  {
266  unsigned int portId = decode(trans.get_address());
267  assert(portId < NR_OF_TARGETS);
268  initiator_socket_type* decodeSocket = &initiator_socket[portId];
269  trans.set_address( trans.get_address() & getAddressMask(portId) );
270 
271  return (*decodeSocket)->transport_dbg(trans);
272  }
273 
274  bool limitRange(unsigned int portId, sc_dt::uint64& low, sc_dt::uint64& high)
275  {
276  sc_dt::uint64 addressOffset = getAddressOffset(portId);
277  sc_dt::uint64 addressMask = getAddressMask(portId);
278 
279  if (low > addressMask) {
280  // Range does not overlap with addressrange for this target
281  return false;
282  }
283 
284  low += addressOffset;
285  if (high > addressMask) {
286  high = addressOffset + addressMask;
287 
288  } else {
289  high += addressOffset;
290  }
291  return true;
292  }
293 
294  bool getDMIPointer(int initiator_id,
295  transaction_type& trans,
296  tlm::tlm_dmi& dmi_data)
297  {
298  // FIXME: DMI not supported for AT bus?
299  sc_dt::uint64 address = trans.get_address();
300 
301  unsigned int portId = decode(address);
302  assert(portId < NR_OF_TARGETS);
303  initiator_socket_type* decodeSocket = &initiator_socket[portId];
304  sc_dt::uint64 maskedAddress = address & getAddressMask(portId);
305 
306  trans.set_address(maskedAddress);
307 
308  bool result =
309  (*decodeSocket)->get_direct_mem_ptr(trans, dmi_data);
310 
311  if (result)
312  {
313  // Range must contain address
314  assert(dmi_data.get_start_address() <= maskedAddress);
315  assert(dmi_data.get_end_address() >= maskedAddress);
316  }
317 
318  // Should always succeed
319  sc_dt::uint64 start, end;
320  start = dmi_data.get_start_address();
321  end = dmi_data.get_end_address();
322 
323  limitRange(portId, start, end);
324 
325  dmi_data.set_start_address(start);
326  dmi_data.set_end_address(end);
327 
328  return result;
329  }
330 
331  void invalidateDMIPointers(int portId,
332  sc_dt::uint64 start_range,
333  sc_dt::uint64 end_range)
334  {
335  // FIXME: probably faster to always invalidate everything?
336 
337  if ((portId >= 0) && !limitRange(portId, start_range, end_range)) {
338  // Range does not fall into address range of target
339  return;
340  }
341 
342  for (unsigned int i = 0; i < NR_OF_INITIATORS; ++i) {
343  (target_socket[i])->invalidate_direct_mem_ptr(start_range, end_range);
344  }
345  }
346 
347 private:
348  void addPendingTransaction(transaction_type& trans,
349  initiator_socket_type* to,
350  int initiatorId)
351  {
352  const ConnectionInfo info = { &target_socket[initiatorId], to };
353  assert(mPendingTransactions.find(&trans) == mPendingTransactions.end());
354  mPendingTransactions[&trans] = info;
355  }
356 
357 private:
358  struct ConnectionInfo {
359  target_socket_type* from;
360  initiator_socket_type* to;
361  };
362  typedef std::map<transaction_type*, ConnectionInfo> PendingTransactions;
363  typedef typename PendingTransactions::iterator PendingTransactionsIterator;
364  typedef typename PendingTransactions::const_iterator PendingTransactionsConstIterator;
365 
366 private:
367  PendingTransactions mPendingTransactions;
368 
372 
376 };
377 
378 #endif
sc_core::sc_event & get_event()
Definition: peq_with_get.h:82
target_socket_type * from
Definition: SimpleBusAT.h:359
tlm_utils::simple_target_socket_tagged< SimpleBusAT > target_socket_type
Definition: SimpleBusAT.h:38
void invalidateDMIPointers(int portId, sc_dt::uint64 start_range, sc_dt::uint64 end_range)
Definition: SimpleBusAT.h:331
void register_get_direct_mem_ptr(MODULE *mod, bool(MODULE::*cb)(int id, transaction_type &, tlm::tlm_dmi &), int id)
void addPendingTransaction(transaction_type &trans, initiator_socket_type *to, int initiatorId)
Definition: SimpleBusAT.h:348
Bitfield< 7 > i
tlm_utils::peq_with_get< transaction_type > mRequestPEQ
Definition: SimpleBusAT.h:369
unsigned int getPortId(const sc_dt::uint64 &address)
Definition: SimpleBusAT.h:72
sc_core::sc_event mEndRequestEvent
Definition: SimpleBusAT.h:371
Bitfield< 3 > exit
Definition: misc.hh:848
void register_nb_transport_bw(MODULE *mod, sync_enum_type(MODULE::*cb)(int, transaction_type &, phase_type &, sc_core::sc_time &), int id)
void set_start_address(sc_dt::uint64 addr)
Definition: dmi.hh:82
sync_enum_type targetNBTransport(int portId, transaction_type &trans, phase_type &phase, sc_core::sc_time &t)
Definition: SimpleBusAT.h:245
const char * name() const
Definition: sc_object.cc:44
void notify(transaction_type &trans, const sc_core::sc_time &t)
Definition: peq_with_get.h:48
initiator_socket_type * to
Definition: SimpleBusAT.h:360
sc_dt::uint64 get_address() const
Definition: gp.hh:184
tlm::tlm_sync_enum sync_enum_type
Definition: SimpleBusAT.h:37
unsigned int decode(const sc_dt::uint64 &address)
Definition: SimpleBusAT.h:87
void set_address(const sc_dt::uint64 address)
Definition: gp.hh:185
sc_dt::uint64 get_start_address() const
Definition: dmi.hh:59
void register_nb_transport_fw(MODULE *mod, sync_enum_type(MODULE::*cb)(int id, transaction_type &, phase_type &, sc_core::sc_time &), int id)
sync_enum_type initiatorNBTransport(int initiator_id, transaction_type &trans, phase_type &phase, sc_core::sc_time &t)
Definition: SimpleBusAT.h:221
#define SC_THREAD(name)
Definition: sc_module.hh:309
tlm_utils::simple_initiator_socket_tagged< SimpleBusAT > initiator_socket_type
Definition: SimpleBusAT.h:39
std::map< transaction_type *, ConnectionInfo > PendingTransactions
Definition: SimpleBusAT.h:362
sc_dt::uint64 getAddressOffset(unsigned int portId)
Definition: SimpleBusAT.h:77
PendingTransactions::const_iterator PendingTransactionsConstIterator
Definition: SimpleBusAT.h:364
bool limitRange(unsigned int portId, sc_dt::uint64 &low, sc_dt::uint64 &high)
Definition: SimpleBusAT.h:274
tlm::tlm_generic_payload transaction_type
Definition: SimpleBusAT.h:35
unsigned int transportDebug(int initiator_id, transaction_type &trans)
Definition: SimpleBusAT.h:264
target_socket_type target_socket[NR_OF_INITIATORS]
Definition: SimpleBusAT.h:42
sc_core::sc_event mEndResponseEvent
Definition: SimpleBusAT.h:375
PendingTransactions::iterator PendingTransactionsIterator
Definition: SimpleBusAT.h:363
const sc_time SC_ZERO_TIME
Definition: sc_time.cc:290
PendingTransactions mPendingTransactions
Definition: SimpleBusAT.h:367
uint64_t uint64
Definition: sc_nbdefs.hh:172
SC_HAS_PROCESS(SimpleBusAT)
SimpleBusAT(sc_core::sc_module_name name)
Definition: SimpleBusAT.h:47
tlm_utils::peq_with_get< transaction_type > mResponsePEQ
Definition: SimpleBusAT.h:373
void register_transport_dbg(MODULE *mod, unsigned int(MODULE::*cb)(int id, transaction_type &), int id)
initiator_socket_type initiator_socket[NR_OF_TARGETS]
Definition: SimpleBusAT.h:43
tlm_sync_enum
Definition: fw_bw_ifs.hh:31
sc_dt::uint64 get_end_address() const
Definition: dmi.hh:60
transaction_type * get_next_transaction()
Definition: peq_with_get.h:64
Bitfield< 5 > t
void set_end_address(sc_dt::uint64 addr)
Definition: dmi.hh:83
void RequestThread()
Definition: SimpleBusAT.h:99
sc_core::sc_event mBeginResponseEvent
Definition: SimpleBusAT.h:374
void ResponseThread()
Definition: SimpleBusAT.h:168
bool getDMIPointer(int initiator_id, transaction_type &trans, tlm::tlm_dmi &dmi_data)
Definition: SimpleBusAT.h:294
void register_invalidate_direct_mem_ptr(MODULE *mod, void(MODULE::*cb)(int, sc_dt::uint64, sc_dt::uint64), int id)
sc_dt::uint64 getAddressMask(unsigned int portId)
Definition: SimpleBusAT.h:82
sc_core::sc_event mBeginRequestEvent
Definition: SimpleBusAT.h:370
tlm::tlm_phase phase_type
Definition: SimpleBusAT.h:36

Generated on Fri Jul 3 2020 15:53:06 for gem5 by doxygen 1.8.13