gem5  v19.0.0.0
All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Modules Pages
gem5_to_tlm.cc
Go to the documentation of this file.
1 /*
2  * Copyright 2019 Google, Inc.
3  *
4  * Redistribution and use in source and binary forms, with or without
5  * modification, are permitted provided that the following conditions are
6  * met: redistributions of source code must retain the above copyright
7  * notice, this list of conditions and the following disclaimer;
8  * redistributions in binary form must reproduce the above copyright
9  * notice, this list of conditions and the following disclaimer in the
10  * documentation and/or other materials provided with the distribution;
11  * neither the name of the copyright holders nor the names of its
12  * contributors may be used to endorse or promote products derived from
13  * this software without specific prior written permission.
14  *
15  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
16  * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
17  * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
18  * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
19  * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
20  * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
21  * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
22  * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
23  * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
24  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
25  * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
26  *
27  * Copyright (c) 2015, University of Kaiserslautern
28  * Copyright (c) 2016, Dresden University of Technology (TU Dresden)
29  * All rights reserved.
30  *
31  * Redistribution and use in source and binary forms, with or without
32  * modification, are permitted provided that the following conditions are
33  * met:
34  *
35  * 1. Redistributions of source code must retain the above copyright notice,
36  * this list of conditions and the following disclaimer.
37  *
38  * 2. Redistributions in binary form must reproduce the above copyright
39  * notice, this list of conditions and the following disclaimer in the
40  * documentation and/or other materials provided with the distribution.
41  *
42  * 3. Neither the name of the copyright holder nor the names of its
43  * contributors may be used to endorse or promote products derived from
44  * this software without specific prior written permission.
45  *
46  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
47  * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
48  * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
49  * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER
50  * OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
51  * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
52  * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
53  * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
54  * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
55  * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
56  * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
57  *
58  * Authors: Gabe Black
59  * Matthias Jung
60  * Abdul Mutaal Ahmad
61  * Christian Menard
62  */
63 
65 
66 #include "params/Gem5ToTlmBridge32.hh"
67 #include "params/Gem5ToTlmBridge64.hh"
68 #include "sim/system.hh"
71 
72 namespace sc_gem5
73 {
74 
80 
87 {
88  tlm::tlm_generic_payload *trans = mm.allocate();
89  trans->acquire();
90 
91  trans->set_address(packet->getAddr());
92 
93  /* Check if this transaction was allocated by mm */
94  sc_assert(trans->has_mm());
95 
96  unsigned int size = packet->getSize();
97  unsigned char *data = packet->getPtr<unsigned char>();
98 
99  trans->set_data_length(size);
100  trans->set_streaming_width(size);
101  trans->set_data_ptr(data);
102 
103  if ((packet->req->getFlags() & Request::NO_ACCESS) != 0) {
104  /* Do nothing */
106  } else if (packet->isRead()) {
108  } else if (packet->isWrite()) {
110  } else {
112  }
113 
114  // Attach the packet pointer to the TLM transaction to keep track.
115  auto *extension = new Gem5SystemC::Gem5Extension(packet);
116  trans->set_auto_extension(extension);
117 
118  return trans;
119 }
120 
121 template <unsigned int BITWIDTH>
122 void
124  tlm::tlm_generic_payload &trans, const tlm::tlm_phase &phase)
125 {
126  sc_core::sc_time delay;
127 
128  if (phase == tlm::END_REQ ||
129  (&trans == blockingRequest && phase == tlm::BEGIN_RESP)) {
130  sc_assert(&trans == blockingRequest);
131  blockingRequest = nullptr;
132 
133  // Did another request arrive while blocked, schedule a retry.
134  if (needToSendRequestRetry) {
135  needToSendRequestRetry = false;
136  bsp.sendRetryReq();
137  }
138  }
139  if (phase == tlm::BEGIN_RESP) {
140  auto &extension = Gem5SystemC::Gem5Extension::getExtension(trans);
141  auto packet = extension.getPacket();
142 
143  sc_assert(!blockingResponse);
144 
145  bool need_retry = false;
146 
147  /*
148  * If the packet was piped through and needs a response, we don't need
149  * to touch the packet and can forward it directly as a response.
150  * Otherwise, we need to make a response and send the transformed
151  * packet.
152  */
153  if (extension.isPipeThrough()) {
154  if (packet->isResponse()) {
155  need_retry = !bsp.sendTimingResp(packet);
156  }
157  } else if (packet->needsResponse()) {
158  packet->makeResponse();
159  need_retry = !bsp.sendTimingResp(packet);
160  }
161 
162  if (need_retry) {
163  blockingResponse = &trans;
164  } else {
165  if (phase == tlm::BEGIN_RESP) {
166  // Send END_RESP and we're finished:
167  tlm::tlm_phase fw_phase = tlm::END_RESP;
169  socket->nb_transport_fw(trans, fw_phase, delay);
170  // Release the transaction with all the extensions.
171  trans.release();
172  }
173  }
174  }
175 }
176 
177 template <unsigned int BITWIDTH>
180 {
181  sc_dt::uint64 start = trans.get_address();
182  sc_dt::uint64 end = start + trans.get_data_length();
183 
184  // Check for a back door we already know about.
185  AddrRange r(start, end);
186  auto it = backdoorMap.contains(r);
187  if (it != backdoorMap.end())
188  return it->second;
189 
190  // If not, ask the target for one.
191  tlm::tlm_dmi dmi_data;
192  if (!socket->get_direct_mem_ptr(trans, dmi_data))
193  return nullptr;
194 
195  // If the target gave us one, translate it to a gem5 MemBackdoor and
196  // store it in our cache.
197  AddrRange dmi_r(dmi_data.get_start_address(), dmi_data.get_end_address());
198  auto backdoor = new MemBackdoor(
199  dmi_r, dmi_data.get_dmi_ptr(), MemBackdoor::NoAccess);
200  backdoor->readable(dmi_data.is_read_allowed());
201  backdoor->writeable(dmi_data.is_write_allowed());
202 
203  backdoorMap.insert(dmi_r, backdoor);
204 
205  return backdoor;
206 }
207 
208 // Similar to TLM's blocking transport (LT)
209 template <unsigned int BITWIDTH>
210 Tick
212 {
213  panic_if(packet->cacheResponding(),
214  "Should not see packets where cache is responding");
215 
216  // Prepare the transaction.
217  auto *trans = packet2payload(packet);
218 
220 
221  if (trans->get_command() != tlm::TLM_IGNORE_COMMAND) {
222  // Execute b_transport:
223  socket->b_transport(*trans, delay);
224  }
225 
226  if (packet->needsResponse())
227  packet->makeResponse();
228 
229  trans->release();
230 
231  return delay.value();
232 }
233 
234 template <unsigned int BITWIDTH>
235 Tick
237  PacketPtr packet, MemBackdoorPtr &backdoor)
238 {
239  panic_if(packet->cacheResponding(),
240  "Should not see packets where cache is responding");
241 
243 
244  // Prepare the transaction.
245  auto *trans = packet2payload(packet);
246 
247  if (trans->get_command() != tlm::TLM_IGNORE_COMMAND) {
248  // Execute b_transport:
249  socket->b_transport(*trans, delay);
250  // If the hint said we could use DMI, set that up.
251  if (trans->is_dmi_allowed())
252  backdoor = getBackdoor(*trans);
253  } else {
254  // There's no transaction to piggy back on, so just request the
255  // backdoor normally.
256  backdoor = getBackdoor(*trans);
257  }
258 
259  if (packet->needsResponse())
260  packet->makeResponse();
261 
262  trans->release();
263 
264  return delay.value();
265 }
266 
267 template <unsigned int BITWIDTH>
268 void
270 {
271  // Snooping should be implemented with tlm_dbg_transport.
272  SC_REPORT_FATAL("Gem5ToTlmBridge",
273  "unimplemented func.: recvFunctionalSnoop");
274 }
275 
276 // Similar to TLM's non-blocking transport (AT).
277 template <unsigned int BITWIDTH>
278 bool
280 {
281  panic_if(packet->cacheResponding(),
282  "Should not see packets where cache is responding");
283 
284  // We should never get a second request after noting that a retry is
285  // required.
286  sc_assert(!needToSendRequestRetry);
287 
288  // Remember if a request comes in while we're blocked so that a retry
289  // can be sent to gem5.
290  if (blockingRequest) {
291  needToSendRequestRetry = true;
292  return false;
293  }
294 
295  /*
296  * NOTE: normal tlm is blocking here. But in our case we return false
297  * and tell gem5 when a retry can be done. This is the main difference
298  * in the protocol:
299  * if (requestInProgress)
300  * {
301  * wait(endRequestEvent);
302  * }
303  * requestInProgress = trans;
304  */
305 
306  // Prepare the transaction.
307  auto *trans = packet2payload(packet);
308 
309  /*
310  * Pay for annotated transport delays.
311  *
312  * The header delay marks the point in time, when the packet first is seen
313  * by the transactor. This is the point in time when the transactor needs
314  * to send the BEGIN_REQ to the SystemC world.
315  *
316  * NOTE: We drop the payload delay here. Normally, the receiver would be
317  * responsible for handling the payload delay. In this case, however,
318  * the receiver is a SystemC module and has no notion of the gem5
319  * transport protocol and we cannot simply forward the
320  * payload delay to the receiving module. Instead, we expect the
321  * receiving SystemC module to model the payload delay by deferring
322  * the END_REQ. This could lead to incorrect delays, if the XBar
323  * payload delay is longer than the time the receiver needs to accept
324  * the request (time between BEGIN_REQ and END_REQ).
325  *
326  * TODO: We could detect the case described above by remembering the
327  * payload delay and comparing it to the time between BEGIN_REQ and
328  * END_REQ. Then, a warning should be printed.
329  */
330  auto delay = sc_core::sc_time::from_value(packet->payloadDelay);
331  // Reset the delays
332  packet->payloadDelay = 0;
333  packet->headerDelay = 0;
334 
335  // Starting TLM non-blocking sequence (AT) Refer to IEEE1666-2011 SystemC
336  // Standard Page 507 for a visualisation of the procedure.
339  status = socket->nb_transport_fw(*trans, phase, delay);
340  // Check returned value:
341  if (status == tlm::TLM_ACCEPTED) {
342  sc_assert(phase == tlm::BEGIN_REQ);
343  // Accepted but is now blocking until END_REQ (exclusion rule).
344  blockingRequest = trans;
345  } else if (status == tlm::TLM_UPDATED) {
346  // The Timing annotation must be honored:
347  sc_assert(phase == tlm::END_REQ || phase == tlm::BEGIN_RESP);
348  auto cb = [this, trans, phase]() { pec(*trans, phase); };
349  system->schedule(new EventFunctionWrapper(cb, "pec", true),
350  curTick() + delay.value());
351  } else if (status == tlm::TLM_COMPLETED) {
352  // Transaction is over nothing has do be done.
353  sc_assert(phase == tlm::END_RESP);
354  trans->release();
355  }
356 
357  return true;
358 }
359 
360 template <unsigned int BITWIDTH>
361 bool
363 {
364  // Snooping should be implemented with tlm_dbg_transport.
365  SC_REPORT_FATAL("Gem5ToTlmBridge",
366  "unimplemented func.: recvTimingSnoopResp");
367  return false;
368 }
369 
370 template <unsigned int BITWIDTH>
371 bool
373 {
374  panic("tryTiming(PacketPtr) isn't implemented.");
375 }
376 
377 template <unsigned int BITWIDTH>
378 void
380 {
381  /* Retry a response */
382  sc_assert(blockingResponse);
383 
384  tlm::tlm_generic_payload *trans = blockingResponse;
385  blockingResponse = nullptr;
386  PacketPtr packet =
388 
389  bool need_retry = !bsp.sendTimingResp(packet);
390 
391  sc_assert(!need_retry);
392 
395  socket->nb_transport_fw(*trans, phase, delay);
396  // Release transaction with all the extensions
397  trans->release();
398 }
399 
400 // Similar to TLM's debug transport.
401 template <unsigned int BITWIDTH>
402 void
404 {
405  // Prepare the transaction.
406  auto *trans = packet2payload(packet);
407 
408  /* Execute Debug Transport: */
409  unsigned int bytes = socket->transport_dbg(*trans);
410  if (bytes != trans->get_data_length()) {
411  SC_REPORT_FATAL("Gem5ToTlmBridge",
412  "debug transport was not completed");
413  }
414 
415  trans->release();
416 }
417 
418 template <unsigned int BITWIDTH>
421  tlm::tlm_phase &phase, sc_core::sc_time &delay)
422 {
423  auto cb = [this, &trans, phase]() { pec(trans, phase); };
424  system->schedule(new EventFunctionWrapper(cb, "pec", true),
425  curTick() + delay.value());
426  return tlm::TLM_ACCEPTED;
427 }
428 
429 template <unsigned int BITWIDTH>
430 void
432  sc_dt::uint64 start_range, sc_dt::uint64 end_range)
433 {
434  AddrRange r(start_range, end_range);
435 
436  for (;;) {
437  auto it = backdoorMap.intersects(r);
438  if (it == backdoorMap.end())
439  break;
440 
441  it->second->invalidate();
442  delete it->second;
443  backdoorMap.erase(it);
444  };
445 }
446 
447 template <unsigned int BITWIDTH>
449  Params *params, const sc_core::sc_module_name &mn) :
450  Gem5ToTlmBridgeBase(mn), bsp(std::string(name()) + ".gem5", *this),
451  socket("tlm_socket"),
452  wrapper(socket, std::string(name()) + ".tlm", InvalidPortID),
453  system(params->system), blockingRequest(nullptr),
454  needToSendRequestRetry(false), blockingResponse(nullptr),
455  addrRanges(params->addr_ranges.begin(), params->addr_ranges.end())
456 {
457 }
458 
459 template <unsigned int BITWIDTH>
460 ::Port &
461 Gem5ToTlmBridge<BITWIDTH>::gem5_getPort(const std::string &if_name, int idx)
462 {
463  if (if_name == "gem5")
464  return bsp;
465  else if (if_name == "tlm")
466  return wrapper;
467 
468  return sc_core::sc_module::gem5_getPort(if_name, idx);
469 }
470 
471 template <unsigned int BITWIDTH>
472 void
474 {
476 
477  socket.register_nb_transport_bw(this, &Gem5ToTlmBridge::nb_transport_bw);
478  socket.register_invalidate_direct_mem_ptr(
481 }
482 
483 } // namespace sc_gem5
484 
486 Gem5ToTlmBridge32Params::create()
487 {
488  return new sc_gem5::Gem5ToTlmBridge<32>(
489  this, sc_core::sc_module_name(name.c_str()));
490 }
491 
493 Gem5ToTlmBridge64Params::create()
494 {
495  return new sc_gem5::Gem5ToTlmBridge<64>(
496  this, sc_core::sc_module_name(name.c_str()));
497 }
#define panic(...)
This implements a cprintf based panic() function.
Definition: logging.hh:167
static Gem5Extension & getExtension(const tlm::tlm_generic_payload *payload)
Definition: sc_ext.cc:52
Tick recvAtomicBackdoor(PacketPtr pkt, MemBackdoorPtr &backdoor)
Definition: gem5_to_tlm.cc:236
void set_streaming_width(const unsigned int streaming_width)
Definition: gp.hh:213
void sendRangeChange() const
Called by the owner to send a range change.
Definition: port.hh:286
tlm_utils::simple_initiator_socket< Gem5ToTlmBridge< BITWIDTH >, BITWIDTH > socket
Definition: gem5_to_tlm.hh:143
const std::string & name()
Definition: trace.cc:54
const PortID InvalidPortID
Definition: types.hh:238
Gem5ToTlmBridgeBaseParams Params
Definition: gem5_to_tlm.hh:195
MemBackdoorPtr getBackdoor(tlm::tlm_generic_payload &trans)
Definition: gem5_to_tlm.cc:179
bool recvTimingReq(PacketPtr packet)
Definition: gem5_to_tlm.cc:279
bool cacheResponding() const
Definition: packet.hh:591
tlm::tlm_generic_payload * packet2payload(PacketPtr packet)
Convert a gem5 packet to a TLM payload by copying all the relevant information to new tlm payload...
Definition: gem5_to_tlm.cc:86
void recvFunctional(PacketPtr packet)
Definition: gem5_to_tlm.cc:403
const char * name() const
Definition: sc_object.cc:46
Overload hash function for BasicBlockRange type.
Definition: vec_reg.hh:586
sc_dt::uint64 get_address() const
Definition: gp.hh:184
bool isWrite() const
Definition: packet.hh:529
T * getPtr()
get a pointer to the data ptr.
Definition: packet.hh:1090
bool isRead() const
Definition: packet.hh:528
bool tryTiming(PacketPtr packet)
Definition: gem5_to_tlm.cc:372
void before_end_of_elaboration() override
Definition: gem5_to_tlm.cc:473
void pec(tlm::tlm_generic_payload &trans, const tlm::tlm_phase &phase)
Definition: gem5_to_tlm.cc:123
void set_address(const sc_dt::uint64 address)
Definition: gp.hh:185
RequestPtr req
A pointer to the original request.
Definition: packet.hh:327
static sc_time from_value(sc_dt::uint64)
Definition: sc_time.cc:212
Bitfield< 5, 0 > status
unsigned getSize() const
Definition: packet.hh:736
The AddrRange class encapsulates an address range, and supports a number of tests to check if two ran...
Definition: addr_range.hh:72
bool recvTimingSnoopResp(PacketPtr packet)
Definition: gem5_to_tlm.cc:362
void invalidate_direct_mem_ptr(sc_dt::uint64 start_range, sc_dt::uint64 end_range)
Definition: gem5_to_tlm.cc:431
Tick curTick()
The current simulated tick.
Definition: core.hh:47
sc_dt::uint64 value() const
Definition: sc_time.cc:117
bool needsResponse() const
Definition: packet.hh:542
uint32_t headerDelay
The extra delay from seeing the packet until the header is transmitted.
Definition: packet.hh:366
uint64_t Tick
Tick count type.
Definition: types.hh:63
unsigned int get_data_length() const
Definition: gp.hh:192
Addr getAddr() const
Definition: packet.hh:726
void set_data_ptr(unsigned char *data)
Definition: gp.hh:189
bool has_mm() const
Definition: gp.hh:140
Bitfield< 8 > bsp
Definition: misc.hh:1054
uint32_t payloadDelay
The extra pipelining delay from seeing the packet until the end of payload is transmitted by the comp...
Definition: packet.hh:384
Gem5ToTlmBridge(Params *p, const sc_core::sc_module_name &mn)
Definition: gem5_to_tlm.cc:448
A Packet is used to encapsulate a transfer between two objects in the memory system (e...
Definition: packet.hh:255
Bitfield< 15 > system
Definition: misc.hh:999
bool readable() const
Definition: backdoor.hh:89
#define sc_assert(expr)
The request should not cause a memory access.
Definition: request.hh:138
void makeResponse()
Take a request packet and modify it in place to be suitable for returning as a response to that reque...
Definition: packet.hh:937
const sc_time SC_ZERO_TIME
Definition: sc_time.cc:292
uint64_t uint64
Definition: sc_nbdefs.hh:172
Gem5SystemC::MemoryManager mm
Instantiate a tlm memory manager that takes care about all the tlm transactions in the system...
Definition: gem5_to_tlm.cc:79
virtual ::Port & gem5_getPort(const std::string &if_name, int idx=-1)
Definition: sc_module.cc:119
virtual gp * allocate()
Definition: sc_mm.cc:53
::Port & gem5_getPort(const std::string &if_name, int idx=-1) override
Definition: gem5_to_tlm.cc:461
void set_command(const tlm_command command)
Definition: gp.hh:181
sc_gem5::TlmInitiatorWrapper< BITWIDTH > wrapper
Definition: gem5_to_tlm.hh:144
tlm_sync_enum
Definition: fw_bw_ifs.hh:31
T * set_auto_extension(T *ext)
Definition: gp.hh:353
#define SC_REPORT_FATAL(msg_type, msg)
void set_data_length(const unsigned int length)
Definition: gp.hh:193
PacketPtr getPacket()
Definition: sc_ext.cc:67
#define panic_if(cond,...)
Conditional panic macro that checks the supplied condition and only panics if the condition is true a...
Definition: logging.hh:185
void recvFunctionalSnoop(PacketPtr packet)
Definition: gem5_to_tlm.cc:269
const char data[]
Tick recvAtomic(PacketPtr packet)
Definition: gem5_to_tlm.cc:211
tlm::tlm_sync_enum nb_transport_bw(tlm::tlm_generic_payload &trans, tlm::tlm_phase &phase, sc_core::sc_time &t)
Definition: gem5_to_tlm.cc:420
virtual void before_end_of_elaboration()
Definition: sc_module.hh:250

Generated on Fri Feb 28 2020 16:27:05 for gem5 by doxygen 1.8.13