gem5  v22.1.0.0
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];
44 
45 public:
49  mRequestPEQ("requestPEQ"),
50  mResponsePEQ("responsePEQ")
51  {
52  for (unsigned int i = 0; i < NR_OF_INITIATORS; ++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 
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 
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  {
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:
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 {
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:
368 
372 
376 };
377 
378 #endif
void invalidateDMIPointers(int portId, sc_dt::uint64 start_range, sc_dt::uint64 end_range)
Definition: SimpleBusAT.h:331
tlm_utils::peq_with_get< transaction_type > mResponsePEQ
Definition: SimpleBusAT.h:373
void ResponseThread()
Definition: SimpleBusAT.h:168
sc_dt::uint64 getAddressMask(unsigned int portId)
Definition: SimpleBusAT.h:82
unsigned int decode(const sc_dt::uint64 &address)
Definition: SimpleBusAT.h:87
std::map< transaction_type *, ConnectionInfo > PendingTransactions
Definition: SimpleBusAT.h:362
tlm::tlm_sync_enum sync_enum_type
Definition: SimpleBusAT.h:37
bool getDMIPointer(int initiator_id, transaction_type &trans, tlm::tlm_dmi &dmi_data)
Definition: SimpleBusAT.h:294
target_socket_type target_socket[NR_OF_INITIATORS]
Definition: SimpleBusAT.h:42
unsigned int transportDebug(int initiator_id, transaction_type &trans)
Definition: SimpleBusAT.h:264
tlm_utils::peq_with_get< transaction_type > mRequestPEQ
Definition: SimpleBusAT.h:369
sc_core::sc_event mBeginResponseEvent
Definition: SimpleBusAT.h:374
unsigned int getPortId(const sc_dt::uint64 &address)
Definition: SimpleBusAT.h:72
sync_enum_type initiatorNBTransport(int initiator_id, transaction_type &trans, phase_type &phase, sc_core::sc_time &t)
Definition: SimpleBusAT.h:221
tlm_utils::simple_initiator_socket_tagged< SimpleBusAT > initiator_socket_type
Definition: SimpleBusAT.h:39
sc_core::sc_event mBeginRequestEvent
Definition: SimpleBusAT.h:370
sync_enum_type targetNBTransport(int portId, transaction_type &trans, phase_type &phase, sc_core::sc_time &t)
Definition: SimpleBusAT.h:245
tlm::tlm_phase phase_type
Definition: SimpleBusAT.h:36
PendingTransactions mPendingTransactions
Definition: SimpleBusAT.h:367
PendingTransactions::iterator PendingTransactionsIterator
Definition: SimpleBusAT.h:363
tlm::tlm_generic_payload transaction_type
Definition: SimpleBusAT.h:35
tlm_utils::simple_target_socket_tagged< SimpleBusAT > target_socket_type
Definition: SimpleBusAT.h:38
sc_dt::uint64 getAddressOffset(unsigned int portId)
Definition: SimpleBusAT.h:77
SC_HAS_PROCESS(SimpleBusAT)
void RequestThread()
Definition: SimpleBusAT.h:99
PendingTransactions::const_iterator PendingTransactionsConstIterator
Definition: SimpleBusAT.h:364
sc_core::sc_event mEndResponseEvent
Definition: SimpleBusAT.h:375
bool limitRange(unsigned int portId, sc_dt::uint64 &low, sc_dt::uint64 &high)
Definition: SimpleBusAT.h:274
initiator_socket_type initiator_socket[NR_OF_TARGETS]
Definition: SimpleBusAT.h:43
sc_core::sc_event mEndRequestEvent
Definition: SimpleBusAT.h:371
void addPendingTransaction(transaction_type &trans, initiator_socket_type *to, int initiatorId)
Definition: SimpleBusAT.h:348
SimpleBusAT(sc_core::sc_module_name name)
Definition: SimpleBusAT.h:47
const char * name() const
Definition: sc_object.cc:44
sc_dt::uint64 get_start_address() const
Definition: dmi.hh:59
sc_dt::uint64 get_end_address() const
Definition: dmi.hh:60
void set_start_address(sc_dt::uint64 addr)
Definition: dmi.hh:82
void set_end_address(sc_dt::uint64 addr)
Definition: dmi.hh:83
void set_address(const sc_dt::uint64 address)
Definition: gp.hh:185
sc_dt::uint64 get_address() const
Definition: gp.hh:184
transaction_type * get_next_transaction()
Definition: peq_with_get.h:64
sc_core::sc_event & get_event()
Definition: peq_with_get.h:82
void notify(transaction_type &trans, const sc_core::sc_time &t)
Definition: peq_with_get.h:48
void register_nb_transport_bw(MODULE *mod, sync_enum_type(MODULE::*cb)(int, transaction_type &, phase_type &, sc_core::sc_time &), int id)
void register_invalidate_direct_mem_ptr(MODULE *mod, void(MODULE::*cb)(int, sc_dt::uint64, sc_dt::uint64), int id)
void register_nb_transport_fw(MODULE *mod, sync_enum_type(MODULE::*cb)(int id, transaction_type &, phase_type &, sc_core::sc_time &), int id)
void register_transport_dbg(MODULE *mod, unsigned int(MODULE::*cb)(int id, transaction_type &), int id)
void register_get_direct_mem_ptr(MODULE *mod, bool(MODULE::*cb)(int id, transaction_type &, tlm::tlm_dmi &), int id)
Bitfield< 7 > i
Definition: misc_types.hh:67
Bitfield< 25, 21 > to
Definition: types.hh:96
Bitfield< 5 > r
Definition: pagetable.hh:60
Bitfield< 51 > t
Definition: pagetable.hh:56
Bitfield< 3 > exit
Definition: misc.hh:855
int addressOffset(Addr addr, Addr base)
high
Definition: intmath.hh:176
const sc_time SC_ZERO_TIME
Definition: sc_time.cc:290
uint64_t uint64
Definition: sc_nbdefs.hh:172
@ BEGIN_RESP
Definition: phase.hh:43
@ END_RESP
Definition: phase.hh:44
@ BEGIN_REQ
Definition: phase.hh:41
@ END_REQ
Definition: phase.hh:42
tlm_sync_enum
Definition: fw_bw_ifs.hh:31
@ TLM_COMPLETED
Definition: fw_bw_ifs.hh:31
@ TLM_ACCEPTED
Definition: fw_bw_ifs.hh:31
@ TLM_UPDATED
Definition: fw_bw_ifs.hh:31
#define SC_THREAD(name)
Definition: sc_module.hh:313
initiator_socket_type * to
Definition: SimpleBusAT.h:360
target_socket_type * from
Definition: SimpleBusAT.h:359

Generated on Wed Dec 21 2022 10:22:42 for gem5 by doxygen 1.9.1