tlm_to_gem5.cc (13821:f9252f27ded7) tlm_to_gem5.cc (13823:040971e0f728)
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) 2016, Dresden University of Technology (TU Dresden)
28 * All rights reserved.
29 *
30 * Redistribution and use in source and binary forms, with or without
31 * modification, are permitted provided that the following conditions are
32 * met:
33 *
34 * 1. Redistributions of source code must retain the above copyright notice,
35 * this list of conditions and the following disclaimer.
36 *
37 * 2. Redistributions in binary form must reproduce the above copyright
38 * notice, this list of conditions and the following disclaimer in the
39 * documentation and/or other materials provided with the distribution.
40 *
41 * 3. Neither the name of the copyright holder nor the names of its
42 * contributors may be used to endorse or promote products derived from
43 * this software without specific prior written permission.
44 *
45 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
46 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
47 * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
48 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER
49 * OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
50 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
51 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
52 * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
53 * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
54 * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
55 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
56 *
57 * Authors: Gabe Black
58 * Christian Menard
59 */
60
61#include "systemc/tlm_bridge/tlm_to_gem5.hh"
62
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) 2016, Dresden University of Technology (TU Dresden)
28 * All rights reserved.
29 *
30 * Redistribution and use in source and binary forms, with or without
31 * modification, are permitted provided that the following conditions are
32 * met:
33 *
34 * 1. Redistributions of source code must retain the above copyright notice,
35 * this list of conditions and the following disclaimer.
36 *
37 * 2. Redistributions in binary form must reproduce the above copyright
38 * notice, this list of conditions and the following disclaimer in the
39 * documentation and/or other materials provided with the distribution.
40 *
41 * 3. Neither the name of the copyright holder nor the names of its
42 * contributors may be used to endorse or promote products derived from
43 * this software without specific prior written permission.
44 *
45 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
46 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
47 * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
48 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER
49 * OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
50 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
51 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
52 * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
53 * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
54 * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
55 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
56 *
57 * Authors: Gabe Black
58 * Christian Menard
59 */
60
61#include "systemc/tlm_bridge/tlm_to_gem5.hh"
62
63#include "params/TlmToGem5Bridge32.hh"
64#include "params/TlmToGem5Bridge64.hh"
63#include "sim/system.hh"
64#include "systemc/ext/core/sc_module_name.hh"
65
66namespace sc_gem5
67{
68
65#include "sim/system.hh"
66#include "systemc/ext/core/sc_module_name.hh"
67
68namespace sc_gem5
69{
70
71template <unsigned int BITWIDTH>
69void
72void
70TlmToGem5Bridge::sendEndReq(tlm::tlm_generic_payload &trans)
73TlmToGem5Bridge<BITWIDTH>::sendEndReq(tlm::tlm_generic_payload &trans)
71{
72 tlm::tlm_phase phase = tlm::END_REQ;
73 auto delay = sc_core::SC_ZERO_TIME;
74
75 auto status = socket->nb_transport_bw(trans, phase, delay);
76 panic_if(status != tlm::TLM_ACCEPTED,
77 "Unexpected status after sending END_REQ");
78}
79
74{
75 tlm::tlm_phase phase = tlm::END_REQ;
76 auto delay = sc_core::SC_ZERO_TIME;
77
78 auto status = socket->nb_transport_bw(trans, phase, delay);
79 panic_if(status != tlm::TLM_ACCEPTED,
80 "Unexpected status after sending END_REQ");
81}
82
83template <unsigned int BITWIDTH>
80void
84void
81TlmToGem5Bridge::sendBeginResp(tlm::tlm_generic_payload &trans,
82 sc_core::sc_time &delay)
85TlmToGem5Bridge<BITWIDTH>::sendBeginResp(tlm::tlm_generic_payload &trans,
86 sc_core::sc_time &delay)
83{
84 tlm::tlm_phase phase = tlm::BEGIN_RESP;
85
86 trans.set_response_status(tlm::TLM_OK_RESPONSE);
87
88 auto status = socket->nb_transport_bw(trans, phase, delay);
89
90 if (status == tlm::TLM_COMPLETED ||
91 (status == tlm::TLM_UPDATED && phase == tlm::END_RESP)) {
92 // transaction completed -> no need to wait for tlm::END_RESP
93 responseInProgress = false;
94 } else if (status == tlm::TLM_ACCEPTED) {
95 // we need to wait for tlm::END_RESP
96 responseInProgress = true;
97 } else {
98 panic("Unexpected status after sending BEGIN_RESP");
99 }
100}
101
87{
88 tlm::tlm_phase phase = tlm::BEGIN_RESP;
89
90 trans.set_response_status(tlm::TLM_OK_RESPONSE);
91
92 auto status = socket->nb_transport_bw(trans, phase, delay);
93
94 if (status == tlm::TLM_COMPLETED ||
95 (status == tlm::TLM_UPDATED && phase == tlm::END_RESP)) {
96 // transaction completed -> no need to wait for tlm::END_RESP
97 responseInProgress = false;
98 } else if (status == tlm::TLM_ACCEPTED) {
99 // we need to wait for tlm::END_RESP
100 responseInProgress = true;
101 } else {
102 panic("Unexpected status after sending BEGIN_RESP");
103 }
104}
105
106template <unsigned int BITWIDTH>
102void
107void
103TlmToGem5Bridge::handleBeginReq(tlm::tlm_generic_payload &trans)
108TlmToGem5Bridge<BITWIDTH>::handleBeginReq(tlm::tlm_generic_payload &trans)
104{
105 sc_assert(!waitForRetry);
106 sc_assert(pendingRequest == nullptr);
107 sc_assert(pendingPacket == nullptr);
108
109 trans.acquire();
110
111 PacketPtr pkt = nullptr;
112
113 Gem5SystemC::Gem5Extension *extension = nullptr;
114 trans.get_extension(extension);
115
116 // If there is an extension, this transaction was initiated by the gem5
117 // world and we can pipe through the original packet. Otherwise, we
118 // generate a new packet based on the transaction.
119 if (extension != nullptr) {
120 extension->setPipeThrough();
121 pkt = extension->getPacket();
122 } else {
123 pkt = generatePacket(trans);
124 }
125
126 auto tlmSenderState = new TlmSenderState(trans);
127 pkt->pushSenderState(tlmSenderState);
128
129 if (bmp.sendTimingReq(pkt)) { // port is free -> send END_REQ immediately
130 sendEndReq(trans);
131 trans.release();
132 } else { // port is blocked -> wait for retry before sending END_REQ
133 waitForRetry = true;
134 pendingRequest = &trans;
135 pendingPacket = pkt;
136 }
137}
138
109{
110 sc_assert(!waitForRetry);
111 sc_assert(pendingRequest == nullptr);
112 sc_assert(pendingPacket == nullptr);
113
114 trans.acquire();
115
116 PacketPtr pkt = nullptr;
117
118 Gem5SystemC::Gem5Extension *extension = nullptr;
119 trans.get_extension(extension);
120
121 // If there is an extension, this transaction was initiated by the gem5
122 // world and we can pipe through the original packet. Otherwise, we
123 // generate a new packet based on the transaction.
124 if (extension != nullptr) {
125 extension->setPipeThrough();
126 pkt = extension->getPacket();
127 } else {
128 pkt = generatePacket(trans);
129 }
130
131 auto tlmSenderState = new TlmSenderState(trans);
132 pkt->pushSenderState(tlmSenderState);
133
134 if (bmp.sendTimingReq(pkt)) { // port is free -> send END_REQ immediately
135 sendEndReq(trans);
136 trans.release();
137 } else { // port is blocked -> wait for retry before sending END_REQ
138 waitForRetry = true;
139 pendingRequest = &trans;
140 pendingPacket = pkt;
141 }
142}
143
144template <unsigned int BITWIDTH>
139void
145void
140TlmToGem5Bridge::handleEndResp(tlm::tlm_generic_payload &trans)
146TlmToGem5Bridge<BITWIDTH>::handleEndResp(tlm::tlm_generic_payload &trans)
141{
142 sc_assert(responseInProgress);
143
144 responseInProgress = false;
145
146 checkTransaction(trans);
147
148 if (needToSendRetry) {
149 bmp.sendRetryResp();
150 needToSendRetry = false;
151 }
152}
153
147{
148 sc_assert(responseInProgress);
149
150 responseInProgress = false;
151
152 checkTransaction(trans);
153
154 if (needToSendRetry) {
155 bmp.sendRetryResp();
156 needToSendRetry = false;
157 }
158}
159
160template <unsigned int BITWIDTH>
154PacketPtr
161PacketPtr
155TlmToGem5Bridge::generatePacket(tlm::tlm_generic_payload &trans)
162TlmToGem5Bridge<BITWIDTH>::generatePacket(tlm::tlm_generic_payload &trans)
156{
157 MemCmd cmd;
158
159 switch (trans.get_command()) {
160 case tlm::TLM_READ_COMMAND:
161 cmd = MemCmd::ReadReq;
162 break;
163 case tlm::TLM_WRITE_COMMAND:
164 cmd = MemCmd::WriteReq;
165 break;
166 case tlm::TLM_IGNORE_COMMAND:
167 return nullptr;
168 default:
169 SC_REPORT_FATAL("TlmToGem5Bridge",
170 "received transaction with unsupported command");
171 }
172
173 Request::Flags flags;
174 auto req = std::make_shared<Request>(
175 trans.get_address(), trans.get_data_length(), flags, masterId);
176
177 /*
178 * Allocate a new Packet. The packet will be deleted when it returns from
179 * the gem5 world as a response.
180 */
181 auto pkt = new Packet(req, cmd);
182 pkt->dataStatic(trans.get_data_ptr());
183
184 return pkt;
185}
186
163{
164 MemCmd cmd;
165
166 switch (trans.get_command()) {
167 case tlm::TLM_READ_COMMAND:
168 cmd = MemCmd::ReadReq;
169 break;
170 case tlm::TLM_WRITE_COMMAND:
171 cmd = MemCmd::WriteReq;
172 break;
173 case tlm::TLM_IGNORE_COMMAND:
174 return nullptr;
175 default:
176 SC_REPORT_FATAL("TlmToGem5Bridge",
177 "received transaction with unsupported command");
178 }
179
180 Request::Flags flags;
181 auto req = std::make_shared<Request>(
182 trans.get_address(), trans.get_data_length(), flags, masterId);
183
184 /*
185 * Allocate a new Packet. The packet will be deleted when it returns from
186 * the gem5 world as a response.
187 */
188 auto pkt = new Packet(req, cmd);
189 pkt->dataStatic(trans.get_data_ptr());
190
191 return pkt;
192}
193
194template <unsigned int BITWIDTH>
187void
195void
188TlmToGem5Bridge::destroyPacket(PacketPtr pkt)
196TlmToGem5Bridge<BITWIDTH>::destroyPacket(PacketPtr pkt)
189{
190 delete pkt;
191}
192
197{
198 delete pkt;
199}
200
201template <unsigned int BITWIDTH>
193void
202void
194TlmToGem5Bridge::checkTransaction(tlm::tlm_generic_payload &trans)
203TlmToGem5Bridge<BITWIDTH>::checkTransaction(tlm::tlm_generic_payload &trans)
195{
196 if (trans.is_response_error()) {
197 std::stringstream ss;
198 ss << "Transaction returned with error, response status = "
199 << trans.get_response_string();
200 SC_REPORT_ERROR("TLM-2", ss.str().c_str());
201 }
202}
203
204{
205 if (trans.is_response_error()) {
206 std::stringstream ss;
207 ss << "Transaction returned with error, response status = "
208 << trans.get_response_string();
209 SC_REPORT_ERROR("TLM-2", ss.str().c_str());
210 }
211}
212
213template <unsigned int BITWIDTH>
204void
214void
205TlmToGem5Bridge::peq_cb(tlm::tlm_generic_payload &trans,
206 const tlm::tlm_phase &phase)
215TlmToGem5Bridge<BITWIDTH>::peq_cb(tlm::tlm_generic_payload &trans,
216 const tlm::tlm_phase &phase)
207{
208 switch (phase) {
209 case tlm::BEGIN_REQ:
210 handleBeginReq(trans);
211 break;
212 case tlm::END_RESP:
213 handleEndResp(trans);
214 break;
215 default:
216 panic("unimplemented phase in callback");
217 }
218}
219
217{
218 switch (phase) {
219 case tlm::BEGIN_REQ:
220 handleBeginReq(trans);
221 break;
222 case tlm::END_RESP:
223 handleEndResp(trans);
224 break;
225 default:
226 panic("unimplemented phase in callback");
227 }
228}
229
230template <unsigned int BITWIDTH>
220tlm::tlm_sync_enum
231tlm::tlm_sync_enum
221TlmToGem5Bridge::nb_transport_fw(
232TlmToGem5Bridge<BITWIDTH>::nb_transport_fw(
222 tlm::tlm_generic_payload &trans, tlm::tlm_phase &phase,
223 sc_core::sc_time &delay)
224{
225 unsigned len = trans.get_data_length();
226 unsigned char *byteEnable = trans.get_byte_enable_ptr();
227 unsigned width = trans.get_streaming_width();
228
229 // check the transaction attributes for unsupported features ...
230 if (byteEnable != 0) {
231 trans.set_response_status(tlm::TLM_BYTE_ENABLE_ERROR_RESPONSE);
232 return tlm::TLM_COMPLETED;
233 }
234 if (width < len) { // is this a burst request?
235 trans.set_response_status(tlm::TLM_BURST_ERROR_RESPONSE);
236 return tlm::TLM_COMPLETED;
237 }
238
239 // ... and queue the valid transaction
240 trans.acquire();
241 peq.notify(trans, phase, delay);
242 return tlm::TLM_ACCEPTED;
243}
244
233 tlm::tlm_generic_payload &trans, tlm::tlm_phase &phase,
234 sc_core::sc_time &delay)
235{
236 unsigned len = trans.get_data_length();
237 unsigned char *byteEnable = trans.get_byte_enable_ptr();
238 unsigned width = trans.get_streaming_width();
239
240 // check the transaction attributes for unsupported features ...
241 if (byteEnable != 0) {
242 trans.set_response_status(tlm::TLM_BYTE_ENABLE_ERROR_RESPONSE);
243 return tlm::TLM_COMPLETED;
244 }
245 if (width < len) { // is this a burst request?
246 trans.set_response_status(tlm::TLM_BURST_ERROR_RESPONSE);
247 return tlm::TLM_COMPLETED;
248 }
249
250 // ... and queue the valid transaction
251 trans.acquire();
252 peq.notify(trans, phase, delay);
253 return tlm::TLM_ACCEPTED;
254}
255
256template <unsigned int BITWIDTH>
245void
257void
246TlmToGem5Bridge::b_transport(tlm::tlm_generic_payload &trans,
247 sc_core::sc_time &t)
258TlmToGem5Bridge<BITWIDTH>::b_transport(tlm::tlm_generic_payload &trans,
259 sc_core::sc_time &t)
248{
249 Gem5SystemC::Gem5Extension *extension = nullptr;
250 trans.get_extension(extension);
251
252 PacketPtr pkt = nullptr;
253
254 // If there is an extension, this transaction was initiated by the gem5
255 // world and we can pipe through the original packet.
256 if (extension != nullptr) {
257 extension->setPipeThrough();
258 pkt = extension->getPacket();
259 } else {
260 pkt = generatePacket(trans);
261 }
262
263 Tick ticks = bmp.sendAtomic(pkt);
264
265 // send an atomic request to gem5
266 panic_if(pkt->needsResponse() && !pkt->isResponse(),
267 "Packet sending failed!\n");
268
269 auto delay =
270 sc_core::sc_time((double)(ticks / SimClock::Int::ps), sc_core::SC_PS);
271
272 // update time
273 t += delay;
274
275 if (extension == nullptr)
276 destroyPacket(pkt);
277
278 trans.set_response_status(tlm::TLM_OK_RESPONSE);
279}
280
260{
261 Gem5SystemC::Gem5Extension *extension = nullptr;
262 trans.get_extension(extension);
263
264 PacketPtr pkt = nullptr;
265
266 // If there is an extension, this transaction was initiated by the gem5
267 // world and we can pipe through the original packet.
268 if (extension != nullptr) {
269 extension->setPipeThrough();
270 pkt = extension->getPacket();
271 } else {
272 pkt = generatePacket(trans);
273 }
274
275 Tick ticks = bmp.sendAtomic(pkt);
276
277 // send an atomic request to gem5
278 panic_if(pkt->needsResponse() && !pkt->isResponse(),
279 "Packet sending failed!\n");
280
281 auto delay =
282 sc_core::sc_time((double)(ticks / SimClock::Int::ps), sc_core::SC_PS);
283
284 // update time
285 t += delay;
286
287 if (extension == nullptr)
288 destroyPacket(pkt);
289
290 trans.set_response_status(tlm::TLM_OK_RESPONSE);
291}
292
293template <unsigned int BITWIDTH>
281unsigned int
294unsigned int
282TlmToGem5Bridge::transport_dbg(tlm::tlm_generic_payload &trans)
295TlmToGem5Bridge<BITWIDTH>::transport_dbg(tlm::tlm_generic_payload &trans)
283{
284 Gem5SystemC::Gem5Extension *extension = nullptr;
285 trans.get_extension(extension);
286
287 // If there is an extension, this transaction was initiated by the gem5
288 // world and we can pipe through the original packet.
289 if (extension != nullptr) {
290 extension->setPipeThrough();
291 bmp.sendFunctional(extension->getPacket());
292 } else {
293 auto pkt = generatePacket(trans);
294 if (pkt) {
295 bmp.sendFunctional(pkt);
296 destroyPacket(pkt);
297 }
298 }
299
300 return trans.get_data_length();
301}
302
296{
297 Gem5SystemC::Gem5Extension *extension = nullptr;
298 trans.get_extension(extension);
299
300 // If there is an extension, this transaction was initiated by the gem5
301 // world and we can pipe through the original packet.
302 if (extension != nullptr) {
303 extension->setPipeThrough();
304 bmp.sendFunctional(extension->getPacket());
305 } else {
306 auto pkt = generatePacket(trans);
307 if (pkt) {
308 bmp.sendFunctional(pkt);
309 destroyPacket(pkt);
310 }
311 }
312
313 return trans.get_data_length();
314}
315
316template <unsigned int BITWIDTH>
303bool
317bool
304TlmToGem5Bridge::get_direct_mem_ptr(tlm::tlm_generic_payload &trans,
305 tlm::tlm_dmi &dmi_data)
318TlmToGem5Bridge<BITWIDTH>::get_direct_mem_ptr(tlm::tlm_generic_payload &trans,
319 tlm::tlm_dmi &dmi_data)
306{
307 return false;
308}
309
320{
321 return false;
322}
323
324template <unsigned int BITWIDTH>
310bool
325bool
311TlmToGem5Bridge::recvTimingResp(PacketPtr pkt)
326TlmToGem5Bridge<BITWIDTH>::recvTimingResp(PacketPtr pkt)
312{
313 // exclusion rule
314 // We need to Wait for END_RESP before sending next BEGIN_RESP
315 if (responseInProgress) {
316 sc_assert(!needToSendRetry);
317 needToSendRetry = true;
318 return false;
319 }
320
321 sc_assert(pkt->isResponse());
322
323 /*
324 * Pay for annotated transport delays.
325 *
326 * See recvTimingReq in sc_slave_port.cc for a detailed description.
327 */
328 auto delay = sc_core::sc_time::from_value(pkt->payloadDelay);
329 // reset the delays
330 pkt->payloadDelay = 0;
331 pkt->headerDelay = 0;
332
333 auto tlmSenderState = dynamic_cast<TlmSenderState*>(pkt->popSenderState());
334 sc_assert(tlmSenderState != nullptr);
335
336 auto &trans = tlmSenderState->trans;
337
338 Gem5SystemC::Gem5Extension *extension = nullptr;
339 trans.get_extension(extension);
340
341 // clean up
342 delete tlmSenderState;
343
344 // If there is an extension the packet was piped through and we must not
345 // delete it. The packet travels back with the transaction.
346 if (extension == nullptr)
347 destroyPacket(pkt);
348 else
349 sc_assert(extension->isPipeThrough());
350
351 sendBeginResp(trans, delay);
352 trans.release();
353
354 return true;
355}
356
327{
328 // exclusion rule
329 // We need to Wait for END_RESP before sending next BEGIN_RESP
330 if (responseInProgress) {
331 sc_assert(!needToSendRetry);
332 needToSendRetry = true;
333 return false;
334 }
335
336 sc_assert(pkt->isResponse());
337
338 /*
339 * Pay for annotated transport delays.
340 *
341 * See recvTimingReq in sc_slave_port.cc for a detailed description.
342 */
343 auto delay = sc_core::sc_time::from_value(pkt->payloadDelay);
344 // reset the delays
345 pkt->payloadDelay = 0;
346 pkt->headerDelay = 0;
347
348 auto tlmSenderState = dynamic_cast<TlmSenderState*>(pkt->popSenderState());
349 sc_assert(tlmSenderState != nullptr);
350
351 auto &trans = tlmSenderState->trans;
352
353 Gem5SystemC::Gem5Extension *extension = nullptr;
354 trans.get_extension(extension);
355
356 // clean up
357 delete tlmSenderState;
358
359 // If there is an extension the packet was piped through and we must not
360 // delete it. The packet travels back with the transaction.
361 if (extension == nullptr)
362 destroyPacket(pkt);
363 else
364 sc_assert(extension->isPipeThrough());
365
366 sendBeginResp(trans, delay);
367 trans.release();
368
369 return true;
370}
371
372template <unsigned int BITWIDTH>
357void
373void
358TlmToGem5Bridge::recvReqRetry()
374TlmToGem5Bridge<BITWIDTH>::recvReqRetry()
359{
360 sc_assert(waitForRetry);
361 sc_assert(pendingRequest != nullptr);
362 sc_assert(pendingPacket != nullptr);
363
364 if (bmp.sendTimingReq(pendingPacket)) {
365 waitForRetry = false;
366 pendingPacket = nullptr;
367
368 auto &trans = *pendingRequest;
369 sendEndReq(trans);
370 trans.release();
371
372 pendingRequest = nullptr;
373 }
374}
375
375{
376 sc_assert(waitForRetry);
377 sc_assert(pendingRequest != nullptr);
378 sc_assert(pendingPacket != nullptr);
379
380 if (bmp.sendTimingReq(pendingPacket)) {
381 waitForRetry = false;
382 pendingPacket = nullptr;
383
384 auto &trans = *pendingRequest;
385 sendEndReq(trans);
386 trans.release();
387
388 pendingRequest = nullptr;
389 }
390}
391
392template <unsigned int BITWIDTH>
376void
393void
377TlmToGem5Bridge::recvRangeChange()
394TlmToGem5Bridge<BITWIDTH>::recvRangeChange()
378{
379 SC_REPORT_WARNING("TlmToGem5Bridge",
380 "received address range change but ignored it");
381}
382
395{
396 SC_REPORT_WARNING("TlmToGem5Bridge",
397 "received address range change but ignored it");
398}
399
400template <unsigned int BITWIDTH>
383::Port &
401::Port &
384TlmToGem5Bridge::gem5_getPort(const std::string &if_name, int idx)
402TlmToGem5Bridge<BITWIDTH>::gem5_getPort(const std::string &if_name, int idx)
385{
386 if (if_name == "gem5")
387 return bmp;
388 else if (if_name == "tlm")
389 return wrapper;
390
391 return sc_core::sc_module::gem5_getPort(if_name, idx);
392}
393
403{
404 if (if_name == "gem5")
405 return bmp;
406 else if (if_name == "tlm")
407 return wrapper;
408
409 return sc_core::sc_module::gem5_getPort(if_name, idx);
410}
411
394TlmToGem5Bridge::TlmToGem5Bridge(
412template <unsigned int BITWIDTH>
413TlmToGem5Bridge<BITWIDTH>::TlmToGem5Bridge(
395 Params *params, const sc_core::sc_module_name &mn) :
414 Params *params, const sc_core::sc_module_name &mn) :
396 sc_core::sc_module(mn), peq(this, &TlmToGem5Bridge::peq_cb),
415 TlmToGem5BridgeBase(mn), peq(this, &TlmToGem5Bridge<BITWIDTH>::peq_cb),
397 waitForRetry(false), pendingRequest(nullptr), pendingPacket(nullptr),
398 needToSendRetry(false), responseInProgress(false),
399 bmp(std::string(name()) + "master", *this), socket("tlm_socket"),
400 wrapper(socket, std::string(name()) + ".tlm", InvalidPortID),
401 system(params->system),
402 masterId(params->system->getGlobalMasterId(
403 std::string("[systemc].") + name()))
404{
405}
406
416 waitForRetry(false), pendingRequest(nullptr), pendingPacket(nullptr),
417 needToSendRetry(false), responseInProgress(false),
418 bmp(std::string(name()) + "master", *this), socket("tlm_socket"),
419 wrapper(socket, std::string(name()) + ".tlm", InvalidPortID),
420 system(params->system),
421 masterId(params->system->getGlobalMasterId(
422 std::string("[systemc].") + name()))
423{
424}
425
426template <unsigned int BITWIDTH>
407void
427void
408TlmToGem5Bridge::before_end_of_elaboration()
428TlmToGem5Bridge<BITWIDTH>::before_end_of_elaboration()
409{
410 /*
411 * Register the TLM non-blocking interface when using gem5 Timing mode and
412 * the TLM blocking interface when using the gem5 Atomic mode.
413 * Then the magic (TM) in simple_target_socket automatically transforms
414 * non-blocking in blocking transactions and vice versa.
415 *
416 * NOTE: The mode may change during execution.
417 */
418 if (system->isTimingMode()) {
419 SC_REPORT_INFO("TlmToGem5Bridge", "register non-blocking interface");
420 socket.register_nb_transport_fw(
429{
430 /*
431 * Register the TLM non-blocking interface when using gem5 Timing mode and
432 * the TLM blocking interface when using the gem5 Atomic mode.
433 * Then the magic (TM) in simple_target_socket automatically transforms
434 * non-blocking in blocking transactions and vice versa.
435 *
436 * NOTE: The mode may change during execution.
437 */
438 if (system->isTimingMode()) {
439 SC_REPORT_INFO("TlmToGem5Bridge", "register non-blocking interface");
440 socket.register_nb_transport_fw(
421 this, &TlmToGem5Bridge::nb_transport_fw);
441 this, &TlmToGem5Bridge<BITWIDTH>::nb_transport_fw);
422 } else if (system->isAtomicMode()) {
423 SC_REPORT_INFO("TlmToGem5Bridge", "register blocking interface");
424 socket.register_b_transport(
442 } else if (system->isAtomicMode()) {
443 SC_REPORT_INFO("TlmToGem5Bridge", "register blocking interface");
444 socket.register_b_transport(
425 this, &TlmToGem5Bridge::b_transport);
445 this, &TlmToGem5Bridge<BITWIDTH>::b_transport);
426 } else {
427 panic("gem5 operates neither in Timing nor in Atomic mode");
428 }
429
446 } else {
447 panic("gem5 operates neither in Timing nor in Atomic mode");
448 }
449
430 socket.register_transport_dbg(this, &TlmToGem5Bridge::transport_dbg);
450 socket.register_transport_dbg(
451 this, &TlmToGem5Bridge<BITWIDTH>::transport_dbg);
431
432 sc_core::sc_module::before_end_of_elaboration();
433}
434
435} // namespace sc_gem5
436
452
453 sc_core::sc_module::before_end_of_elaboration();
454}
455
456} // namespace sc_gem5
457
437sc_gem5::TlmToGem5Bridge *
438TlmToGem5BridgeParams::create()
458sc_gem5::TlmToGem5Bridge<32> *
459TlmToGem5Bridge32Params::create()
439{
460{
440 return new sc_gem5::TlmToGem5Bridge(
461 return new sc_gem5::TlmToGem5Bridge<32>(
441 this, sc_core::sc_module_name(name.c_str()));
442}
462 this, sc_core::sc_module_name(name.c_str()));
463}
464
465sc_gem5::TlmToGem5Bridge<64> *
466TlmToGem5Bridge64Params::create()
467{
468 return new sc_gem5::TlmToGem5Bridge<64>(
469 this, sc_core::sc_module_name(name.c_str()));
470}