gem5  v22.1.0.0
SimpleLTInitiator_ext.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 __SIMPLE_LT_INITIATOR_EXT_H__
21 #define __SIMPLE_LT_INITIATOR_EXT_H__
22 
23 #include "tlm.h"
24 #include "tlm_utils/simple_initiator_socket.h"
25 #include "my_extension.h"
26 
27 #include <systemc>
28 #include <cassert>
29 #include <iostream>
30 #include <iomanip>
31 #include <map>
32 
34 {
35 public:
42 
43 public:
45 
46 public:
49  unsigned int nrOfTransactions = 0x5,
50  unsigned int baseAddress = 0x0) :
52  socket("socket"),
53  mNrOfTransactions(nrOfTransactions),
54  mBaseAddress(baseAddress),
56  {
58 
59  // register nb_transport method
62 
63  // Initiator thread
64  SC_THREAD(run);
65 
66  }
67 
69  {
70  // initialize DMI hint:
71  trans.set_dmi_allowed(false);
72 
74  {
77  trans.set_data_ptr(reinterpret_cast<unsigned char*>(&mData));
79 
80  }
81  else if (mTransactionCount < 2 * mNrOfTransactions)
82  {
84  mData = 0;
85  trans.set_data_ptr(reinterpret_cast<unsigned char*>(&mData));
87 
88  }
89  else
90  {
91  return false;
92  }
93 
95  return true;
96  }
97 
99  {
100  if (trans.get_command() == tlm::TLM_WRITE_COMMAND)
101  {
102  std::cout << name() << ": Send write request: A = 0x"
103  << std::hex << (unsigned int)trans.get_address()
104  << ", D = 0x" << mData << std::dec
105  << " @ " << sc_core::sc_time_stamp() << std::endl;
106 
107  }
108  else
109  {
110  std::cout << name() << ": Send read request: A = 0x"
111  << std::hex << (unsigned int)trans.get_address()
112  << std::dec
113  << " @ " << sc_core::sc_time_stamp() << std::endl;
114  }
115  }
116 
118  {
119  if (trans.get_response_status() != tlm::TLM_OK_RESPONSE) {
120  std::cout << name() << ": Received error response @ "
121  << sc_core::sc_time_stamp() << std::endl;
122  }
123  else
124  {
125  std::cout << name() << ": Received ok response";
126  if (trans.get_command() == tlm::TLM_READ_COMMAND) {
127  std::cout << ": D = 0x" << std::hex << mData << std::dec;
128  }
129  std::cout << " @ " << sc_core::sc_time_stamp() << std::endl;
130  }
131  }
132 
133  void run()
134  {
135  transaction_type trans;
136  phase_type phase;
138  // make sure that our transaction has the proper extension:
139  my_extension* tmp_ext = new my_extension();
140  tmp_ext->m_data = 11;
141 
142  trans.set_extension(tmp_ext);
143 
144  while (initTransaction(trans))
145  {
146  // Create transaction and initialise phase and t
147  phase = tlm::BEGIN_REQ;
149 
150  logStartTransation(trans);
152  // DMI handling:
153  // We use the DMI hint to check if it makes sense to ask for
154  // DMI pointers. The pattern is:
155  // - if the address is covered by a DMI region do a DMI access
156  // - otherwise do a normal transaction
157  // -> check if we get a DMI hint and acquire the DMI pointers if it
158  // is set
160 
161  // Check if the address is covered by our DMI region
162  if ( (trans.get_address() >= mDMIData.get_start_address()) &&
163  (trans.get_address() <= mDMIData.get_end_address()) )
164  {
165  // We can handle the data here. As the logEndTransaction is
166  // assuming something to happen in the data structure, we really
167  // need to do this:
170  if (trans.get_command() == tlm::TLM_WRITE_COMMAND) {
171  *(unsigned int*)&mDMIData.get_dmi_ptr()[tmp] = mData;
172 
173  } else {
174  mData = *(unsigned int*)&mDMIData.get_dmi_ptr()[tmp];
175  }
176 
177  // Do the wait immediately. Note that doing the wait here eats
178  // almost all the performance anyway, so we only gain something
179  // if we're using temporal decoupling.
180  if (trans.get_command() == tlm::TLM_WRITE_COMMAND) {
182 
183  } else {
185  }
186 
187  logEndTransaction(trans);
188 
189  } else { // we need a full transaction
190  switch (socket->nb_transport_fw(trans, phase, t)) {
191  case tlm::TLM_COMPLETED:
192  // Transaction Finished, wait for the returned delay
193  wait(t);
194  break;
195 
196  case tlm::TLM_ACCEPTED:
197  case tlm::TLM_UPDATED:
198  // Transaction not yet finished, wait for the end of it
199  wait(mEndEvent);
200  break;
201 
202  default:
203  sc_assert(0); exit(1);
204  };
205 
206  logEndTransaction(trans);
207 
208  // Acquire DMI pointer if one is available:
209  if (trans.is_dmi_allowed())
210  {
211  trans.set_write();
212  dmi_type tmp;
213  if (socket->get_direct_mem_ptr(trans,
214  tmp))
215  {
216  // FIXME: No support for separate read/write ranges
218  mDMIData = tmp;
219  }
220  }
221  }
222  }
223  delete tmp_ext;
224  wait();
225 
226  }
227 
229  phase_type& phase,
231  {
232  switch (phase) {
233  case tlm::END_REQ:
234  // Request phase ended
235  return tlm::TLM_ACCEPTED;
236 
237  case tlm::BEGIN_RESP:
238  sc_assert(t == sc_core::SC_ZERO_TIME); // FIXME: can t != 0?
239  mEndEvent.notify(t);
240  // Not needed to update the phase if true is returned
241  return tlm::TLM_COMPLETED;
242 
243  case tlm::BEGIN_REQ: // fall-through
244  case tlm::END_RESP: // fall-through
245  default:
246  // A target should never call nb_transport with these phases
247  sc_assert(0); exit(1);
248 // return tlm::TLM_COMPLETED; //unreachable code
249  };
250  }
251 
252  void invalidate(dmi_type& dmiData)
253  {
254  dmiData.set_start_address(1);
255  dmiData.set_end_address(0);
256  }
257 
258  // Invalidate DMI pointer(s)
260  sc_dt::uint64 end_range)
261  {
262  // do the invalidation if there is an address range overlap
263  if (start_range <= mDMIData.get_end_address ()&&
264  end_range >= mDMIData.get_start_address()) {
265  std::cout << name() << ": got DMI pointer invalidation"
266  << " @ " << sc_core::sc_time_stamp() << std::endl;
267 
269  } else {
270  std::cout << name() << ": ignored DMI invalidation for addresses "
271  << std::hex << start_range << ", "
272  << end_range << std::dec
273  << " @ " << sc_core::sc_time_stamp() << std::endl;
274  }
275  }
276 
277  // Test for transport_dbg, this one should fail in bus_dmi as we address
278  // a target that doesn't support transport_dbg:
279  // FIXME: use a configurable address
281  {
282  std::cout << name() << ", <<SimpleLTInitiator1>>:" << std::endl
283  << std::endl;
284  unsigned char data[32];
285 
286  transaction_type trans;
287  trans.set_address(mBaseAddress);
288  trans.set_data_length(32);
289  trans.set_data_ptr(data);
290  trans.set_read();
291 
292  unsigned int n = socket->transport_dbg(trans);
293 
294  std::cout << "Mem @" << std::hex << mBaseAddress << std::endl;
295  unsigned int j = 0;
296 
297  if (n > 0)
298  {
299  // always align endianness, so that we don't get a diff when
300  // printing the raw data
301  int e_start = 0;
302  int e_end = 4;
303  int e_increment = 1;
305  {
306  e_start = 3;
307  e_end = -1;
308  e_increment = -1;
309  }
310 
311  for (unsigned int i=0; i<n; i+=4)
312  {
313  for (int k=e_start; k!=e_end; k+=e_increment)
314  {
315  std::cout << std::setw(2) << std::setfill('0')
316  << (int)data[i+k];
317  j++;
318  if (j==16) {
319  j=0;
320  std::cout << std::endl;
321  } else {
322  std::cout << " ";
323  }
324  }
325  }
326  }
327  else
328  {
329  std::cout << "OK: debug transaction didn't give data." << std::endl;
330  }
331  std::cout << std::dec << std::endl;
332  }
333 private:
335 
337  unsigned int mNrOfTransactions;
338  unsigned int mBaseAddress;
339  unsigned int mTransactionCount;
340  unsigned int mData;
341 };
342 
343 #endif
const char data[]
SC_HAS_PROCESS(SimpleLTInitiator_ext)
void logStartTransation(transaction_type &trans)
tlm::tlm_sync_enum sync_enum_type
SimpleLTInitiator_ext(sc_core::sc_module_name name, unsigned int nrOfTransactions=0x5, unsigned int baseAddress=0x0)
tlm::tlm_generic_payload transaction_type
void logEndTransaction(transaction_type &trans)
tlm_utils::simple_initiator_socket< SimpleLTInitiator_ext, 32, my_extended_payload_types > initiator_socket_type
initiator_socket_type socket
bool initTransaction(transaction_type &trans)
void invalidate(dmi_type &dmiData)
void invalidate_direct_mem_ptr(sc_dt::uint64 start_range, sc_dt::uint64 end_range)
sync_enum_type myNBTransport(transaction_type &trans, phase_type &phase, sc_core::sc_time &t)
const char * name() const
Definition: sc_object.cc:44
unsigned char * get_dmi_ptr() const
Definition: dmi.hh:58
sc_dt::uint64 get_start_address() const
Definition: dmi.hh:59
sc_core::sc_time get_write_latency() const
Definition: dmi.hh:62
sc_dt::uint64 get_end_address() const
Definition: dmi.hh:60
bool is_read_write_allowed() const
Definition: dmi.hh:76
sc_core::sc_time get_read_latency() const
Definition: dmi.hh:61
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_data_ptr(unsigned char *data)
Definition: gp.hh:189
void set_dmi_allowed(bool dmi_allowed)
Definition: gp.hh:239
void set_response_status(const tlm_response_status response_status)
Definition: gp.hh:204
void set_address(const sc_dt::uint64 address)
Definition: gp.hh:185
T * set_extension(T *ext)
Definition: gp.hh:340
void set_command(const tlm_command command)
Definition: gp.hh:181
sc_dt::uint64 get_address() const
Definition: gp.hh:184
tlm_response_status get_response_status() const
Definition: gp.hh:199
void set_data_length(const unsigned int length)
Definition: gp.hh:193
bool is_dmi_allowed() const
Definition: gp.hh:244
tlm_command get_command() const
Definition: gp.hh:180
void register_nb_transport_bw(MODULE *mod, sync_enum_type(MODULE::*cb)(transaction_type &, phase_type &, sc_core::sc_time &))
void register_invalidate_direct_mem_ptr(MODULE *mod, void(MODULE::*cb)(sc_dt::uint64, sc_dt::uint64))
Bitfield< 31 > n
Definition: misc_types.hh:462
Bitfield< 7 > i
Definition: misc_types.hh:67
Bitfield< 24 > j
Definition: misc_types.hh:57
Bitfield< 23 > k
Definition: dt_constants.hh:81
Bitfield< 51 > t
Definition: pagetable.hh:56
Bitfield< 3 > exit
Definition: misc.hh:855
const sc_time SC_ZERO_TIME
Definition: sc_time.cc:290
const sc_time & sc_time_stamp()
Definition: sc_main.cc:127
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_READ_COMMAND
Definition: gp.hh:84
@ TLM_WRITE_COMMAND
Definition: gp.hh:85
@ TLM_OK_RESPONSE
Definition: gp.hh:91
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
bool host_has_little_endianness()
Definition: helpers.hh:43
#define SC_THREAD(name)
Definition: sc_module.hh:313
#define sc_assert(expr)

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