gem5  v21.1.0.2
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:
36  typedef tlm::tlm_phase phase_type;
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 
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 
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 
168  void ResponseThread()
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 
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
tlm_utils::simple_target_socket_tagged_b::register_transport_dbg
void register_transport_dbg(MODULE *mod, unsigned int(MODULE::*cb)(int id, transaction_type &), int id)
Definition: simple_target_socket.h:688
tlm_utils::peq_with_get::get_next_transaction
transaction_type * get_next_transaction()
Definition: peq_with_get.h:98
SimpleBusAT::target_socket_type
tlm_utils::simple_target_socket_tagged< SimpleBusAT > target_socket_type
Definition: SimpleBusAT.h:55
tlm_utils::simple_initiator_socket_tagged_b::register_invalidate_direct_mem_ptr
void register_invalidate_direct_mem_ptr(MODULE *mod, void(MODULE::*cb)(int, sc_dt::uint64, sc_dt::uint64), int id)
Definition: simple_initiator_socket.h:238
tlm_utils::simple_initiator_socket_tagged_b::register_nb_transport_bw
void register_nb_transport_bw(MODULE *mod, sync_enum_type(MODULE::*cb)(int, transaction_type &, phase_type &, sc_core::sc_time &), int id)
Definition: simple_initiator_socket.h:228
SimpleBusAT::ResponseThread
void ResponseThread()
Definition: SimpleBusAT.h:185
SC_THREAD
#define SC_THREAD(name)
Definition: sc_module.hh:310
SimpleBusAT::mRequestPEQ
tlm_utils::peq_with_get< transaction_type > mRequestPEQ
Definition: SimpleBusAT.h:386
SimpleBusAT::getPortId
unsigned int getPortId(const sc_dt::uint64 &address)
Definition: SimpleBusAT.h:89
SimpleBusAT::getDMIPointer
bool getDMIPointer(int initiator_id, transaction_type &trans, tlm::tlm_dmi &dmi_data)
Definition: SimpleBusAT.h:311
SimpleBusAT::mEndRequestEvent
sc_core::sc_event mEndRequestEvent
Definition: SimpleBusAT.h:388
SimpleBusAT::getAddressMask
sc_dt::uint64 getAddressMask(unsigned int portId)
Definition: SimpleBusAT.h:99
sc_core::sc_module
Definition: sc_module.hh:98
tlm::tlm_phase
Definition: phase.hh:47
SimpleBusAT::mBeginRequestEvent
sc_core::sc_event mBeginRequestEvent
Definition: SimpleBusAT.h:387
SimpleBusAT::invalidateDMIPointers
void invalidateDMIPointers(int portId, sc_dt::uint64 start_range, sc_dt::uint64 end_range)
Definition: SimpleBusAT.h:348
tlm::TLM_COMPLETED
@ TLM_COMPLETED
Definition: fw_bw_ifs.hh:65
tlm::tlm_dmi
Definition: dmi.hh:46
tlm::TLM_UPDATED
@ TLM_UPDATED
Definition: fw_bw_ifs.hh:65
SimpleBusAT::decode
unsigned int decode(const sc_dt::uint64 &address)
Definition: SimpleBusAT.h:104
tlm::END_REQ
@ END_REQ
Definition: phase.hh:42
sc_core::SC_ZERO_TIME
const sc_time SC_ZERO_TIME
Definition: sc_time.cc:290
SimpleBusAT::sync_enum_type
tlm::tlm_sync_enum sync_enum_type
Definition: SimpleBusAT.h:54
tlm_utils::peq_with_get::notify
void notify(transaction_type &trans, const sc_core::sc_time &t)
Definition: peq_with_get.h:82
SimpleBusAT::targetNBTransport
sync_enum_type targetNBTransport(int portId, transaction_type &trans, phase_type &phase, sc_core::sc_time &t)
Definition: SimpleBusAT.h:262
gem5::ArmISA::i
Bitfield< 7 > i
Definition: misc_types.hh:66
gem5::PowerISA::to
Bitfield< 25, 21 > to
Definition: types.hh:96
SimpleBusAT::transaction_type
tlm::tlm_generic_payload transaction_type
Definition: SimpleBusAT.h:52
tlm_utils::peq_with_get::get_event
sc_core::sc_event & get_event()
Definition: peq_with_get.h:116
tlm_utils::peq_with_get< transaction_type >
SimpleBusAT::transportDebug
unsigned int transportDebug(int initiator_id, transaction_type &trans)
Definition: SimpleBusAT.h:281
tlm::tlm_dmi::set_end_address
void set_end_address(sc_dt::uint64 addr)
Definition: dmi.hh:117
gem5::high
high
Definition: intmath.hh:176
SimpleBusAT::ConnectionInfo
Definition: SimpleBusAT.h:375
SimpleBusAT::ConnectionInfo::from
target_socket_type * from
Definition: SimpleBusAT.h:376
sc_dt::uint64
uint64_t uint64
Definition: sc_nbdefs.hh:206
SimpleBusAT::PendingTransactionsConstIterator
PendingTransactions::const_iterator PendingTransactionsConstIterator
Definition: SimpleBusAT.h:381
sc_core::sc_event
Definition: sc_event.hh:169
sc_core::sc_time
Definition: sc_time.hh:49
tlm::tlm_dmi::get_end_address
sc_dt::uint64 get_end_address() const
Definition: dmi.hh:94
SimpleBusAT::target_socket
target_socket_type target_socket[NR_OF_INITIATORS]
Definition: SimpleBusAT.h:59
SimpleBusAT::mEndResponseEvent
sc_core::sc_event mEndResponseEvent
Definition: SimpleBusAT.h:392
tlm::tlm_dmi::get_start_address
sc_dt::uint64 get_start_address() const
Definition: dmi.hh:93
SimpleBusAT::initiatorNBTransport
sync_enum_type initiatorNBTransport(int initiator_id, transaction_type &trans, phase_type &phase, sc_core::sc_time &t)
Definition: SimpleBusAT.h:238
SimpleBusAT::getAddressOffset
sc_dt::uint64 getAddressOffset(unsigned int portId)
Definition: SimpleBusAT.h:94
sc_core::sc_module_name
Definition: sc_module_name.hh:41
SimpleBusAT::SC_HAS_PROCESS
SC_HAS_PROCESS(SimpleBusAT)
SimpleBusAT::SimpleBusAT
SimpleBusAT(sc_core::sc_module_name name)
Definition: SimpleBusAT.h:64
SimpleBusAT::initiator_socket_type
tlm_utils::simple_initiator_socket_tagged< SimpleBusAT > initiator_socket_type
Definition: SimpleBusAT.h:56
gem5::ArmISA::t
Bitfield< 5 > t
Definition: misc_types.hh:70
SimpleBusAT::mResponsePEQ
tlm_utils::peq_with_get< transaction_type > mResponsePEQ
Definition: SimpleBusAT.h:390
tlm::END_RESP
@ END_RESP
Definition: phase.hh:44
SimpleBusAT::PendingTransactions
std::map< transaction_type *, ConnectionInfo > PendingTransactions
Definition: SimpleBusAT.h:379
tlm_utils::simple_target_socket_tagged< SimpleBusAT >
gem5::X86ISA::exit
Bitfield< 3 > exit
Definition: misc.hh:854
sc_core::sc_event::notify
void notify()
Definition: sc_event.cc:337
SimpleBusAT::limitRange
bool limitRange(unsigned int portId, sc_dt::uint64 &low, sc_dt::uint64 &high)
Definition: SimpleBusAT.h:291
tlm::BEGIN_REQ
@ BEGIN_REQ
Definition: phase.hh:41
SimpleBusAT::initiator_socket
initiator_socket_type initiator_socket[NR_OF_TARGETS]
Definition: SimpleBusAT.h:60
tlm::tlm_generic_payload
Definition: gp.hh:133
SimpleBusAT::PendingTransactionsIterator
PendingTransactions::iterator PendingTransactionsIterator
Definition: SimpleBusAT.h:380
tlm_utils::simple_target_socket_tagged_b::register_nb_transport_fw
void register_nb_transport_fw(MODULE *mod, sync_enum_type(MODULE::*cb)(int id, transaction_type &, phase_type &, sc_core::sc_time &), int id)
Definition: simple_target_socket.h:666
sc_core::sc_object::name
const char * name() const
Definition: sc_object.cc:44
tlm::tlm_generic_payload::set_address
void set_address(const sc_dt::uint64 address)
Definition: gp.hh:202
tlm_utils::simple_initiator_socket_tagged< SimpleBusAT >
SimpleBusAT::phase_type
tlm::tlm_phase phase_type
Definition: SimpleBusAT.h:53
tlm::tlm_sync_enum
tlm_sync_enum
Definition: fw_bw_ifs.hh:48
sc_core::sc_module::wait
void wait()
Definition: sc_module.cc:428
gem5::MipsISA::r
r
Definition: pra_constants.hh:98
SimpleBusAT::mPendingTransactions
PendingTransactions mPendingTransactions
Definition: SimpleBusAT.h:384
tlm::tlm_dmi::set_start_address
void set_start_address(sc_dt::uint64 addr)
Definition: dmi.hh:116
gem5::ruby::addressOffset
int addressOffset(Addr addr, Addr base)
Definition: RubySlicc_Util.hh:182
tlm_utils::simple_target_socket_tagged_b::register_get_direct_mem_ptr
void register_get_direct_mem_ptr(MODULE *mod, bool(MODULE::*cb)(int id, transaction_type &, tlm::tlm_dmi &), int id)
Definition: simple_target_socket.h:697
SimpleBusAT
Definition: SimpleBusAT.h:32
SimpleBusAT::ConnectionInfo::to
initiator_socket_type * to
Definition: SimpleBusAT.h:377
tlm::tlm_generic_payload::get_address
sc_dt::uint64 get_address() const
Definition: gp.hh:201
SimpleBusAT::addPendingTransaction
void addPendingTransaction(transaction_type &trans, initiator_socket_type *to, int initiatorId)
Definition: SimpleBusAT.h:365
SimpleBusAT::RequestThread
void RequestThread()
Definition: SimpleBusAT.h:116
tlm::BEGIN_RESP
@ BEGIN_RESP
Definition: phase.hh:43
SimpleBusAT::mBeginResponseEvent
sc_core::sc_event mBeginResponseEvent
Definition: SimpleBusAT.h:391
tlm::TLM_ACCEPTED
@ TLM_ACCEPTED
Definition: fw_bw_ifs.hh:65

Generated on Tue Sep 21 2021 12:25:57 for gem5 by doxygen 1.8.17