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 64#include "systemc/tlm_bridge/gem5_to_tlm.hh" 65 66#include "params/Gem5ToTlmBridge32.hh" 67#include "params/Gem5ToTlmBridge64.hh" 68#include "sim/system.hh" 69#include "systemc/tlm_bridge/sc_ext.hh" 70#include "systemc/tlm_bridge/sc_mm.hh" 71 72namespace sc_gem5 73{ 74 75/** 76 * Instantiate a tlm memory manager that takes care about all the 77 * tlm transactions in the system. 78 */ 79Gem5SystemC::MemoryManager mm; 80 81/** 82 * Convert a gem5 packet to a TLM payload by copying all the relevant
| 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 64#include "systemc/tlm_bridge/gem5_to_tlm.hh" 65 66#include "params/Gem5ToTlmBridge32.hh" 67#include "params/Gem5ToTlmBridge64.hh" 68#include "sim/system.hh" 69#include "systemc/tlm_bridge/sc_ext.hh" 70#include "systemc/tlm_bridge/sc_mm.hh" 71 72namespace sc_gem5 73{ 74 75/** 76 * Instantiate a tlm memory manager that takes care about all the 77 * tlm transactions in the system. 78 */ 79Gem5SystemC::MemoryManager mm; 80 81/** 82 * Convert a gem5 packet to a TLM payload by copying all the relevant
|
83 * information to a previously allocated tlm payload
| 83 * information to new tlm payload.
|
84 */
| 84 */
|
85void 86packet2payload(PacketPtr packet, tlm::tlm_generic_payload &trans)
| 85tlm::tlm_generic_payload * 86packet2payload(PacketPtr packet)
|
87{
| 87{
|
88 trans.set_address(packet->getAddr());
| 88 tlm::tlm_generic_payload *trans = mm.allocate(); 89 trans->acquire();
|
89
| 90
|
| 91 trans->set_address(packet->getAddr()); 92
|
90 /* Check if this transaction was allocated by mm */
| 93 /* Check if this transaction was allocated by mm */
|
91 sc_assert(trans.has_mm());
| 94 sc_assert(trans->has_mm());
|
92 93 unsigned int size = packet->getSize(); 94 unsigned char *data = packet->getPtr<unsigned char>(); 95
| 95 96 unsigned int size = packet->getSize(); 97 unsigned char *data = packet->getPtr<unsigned char>(); 98
|
96 trans.set_data_length(size); 97 trans.set_streaming_width(size); 98 trans.set_data_ptr(data);
| 99 trans->set_data_length(size); 100 trans->set_streaming_width(size); 101 trans->set_data_ptr(data);
|
99
| 102
|
100 if (packet->isRead()) { 101 trans.set_command(tlm::TLM_READ_COMMAND);
| 103 if ((packet->req->getFlags() & Request::NO_ACCESS) != 0) { 104 /* Do nothing */ 105 trans->set_command(tlm::TLM_IGNORE_COMMAND); 106 } else if (packet->isRead()) { 107 trans->set_command(tlm::TLM_READ_COMMAND);
|
102 } else if (packet->isInvalidate()) { 103 /* Do nothing */
| 108 } else if (packet->isInvalidate()) { 109 /* Do nothing */
|
| 110 trans->set_command(tlm::TLM_IGNORE_COMMAND);
|
104 } else if (packet->isWrite()) {
| 111 } else if (packet->isWrite()) {
|
105 trans.set_command(tlm::TLM_WRITE_COMMAND);
| 112 trans->set_command(tlm::TLM_WRITE_COMMAND);
|
106 } else { 107 SC_REPORT_FATAL("Gem5ToTlmBridge", "No R/W packet"); 108 }
| 113 } else { 114 SC_REPORT_FATAL("Gem5ToTlmBridge", "No R/W packet"); 115 }
|
| 116 117 // Attach the packet pointer to the TLM transaction to keep track. 118 auto *extension = new Gem5SystemC::Gem5Extension(packet); 119 trans->set_auto_extension(extension); 120 121 return trans;
|
109} 110 111template <unsigned int BITWIDTH> 112void 113Gem5ToTlmBridge<BITWIDTH>::pec( 114 Gem5SystemC::PayloadEvent<Gem5ToTlmBridge<BITWIDTH>> *pe, 115 tlm::tlm_generic_payload &trans, const tlm::tlm_phase &phase) 116{ 117 sc_core::sc_time delay; 118 119 if (phase == tlm::END_REQ || 120 (&trans == blockingRequest && phase == tlm::BEGIN_RESP)) { 121 sc_assert(&trans == blockingRequest); 122 blockingRequest = nullptr; 123 124 // Did another request arrive while blocked, schedule a retry. 125 if (needToSendRequestRetry) { 126 needToSendRequestRetry = false; 127 bsp.sendRetryReq(); 128 } 129 } 130 if (phase == tlm::BEGIN_RESP) { 131 auto &extension = Gem5SystemC::Gem5Extension::getExtension(trans); 132 auto packet = extension.getPacket(); 133 134 sc_assert(!blockingResponse); 135 136 bool need_retry = false; 137 138 /* 139 * If the packet was piped through and needs a response, we don't need 140 * to touch the packet and can forward it directly as a response. 141 * Otherwise, we need to make a response and send the transformed 142 * packet. 143 */ 144 if (extension.isPipeThrough()) { 145 if (packet->isResponse()) { 146 need_retry = !bsp.sendTimingResp(packet); 147 } 148 } else if (packet->needsResponse()) { 149 packet->makeResponse(); 150 need_retry = !bsp.sendTimingResp(packet); 151 } 152 153 if (need_retry) { 154 blockingResponse = &trans; 155 } else { 156 if (phase == tlm::BEGIN_RESP) { 157 // Send END_RESP and we're finished: 158 tlm::tlm_phase fw_phase = tlm::END_RESP; 159 sc_core::sc_time delay = sc_core::SC_ZERO_TIME; 160 socket->nb_transport_fw(trans, fw_phase, delay); 161 // Release the transaction with all the extensions. 162 trans.release(); 163 } 164 } 165 } 166 delete pe; 167} 168
| 122} 123 124template <unsigned int BITWIDTH> 125void 126Gem5ToTlmBridge<BITWIDTH>::pec( 127 Gem5SystemC::PayloadEvent<Gem5ToTlmBridge<BITWIDTH>> *pe, 128 tlm::tlm_generic_payload &trans, const tlm::tlm_phase &phase) 129{ 130 sc_core::sc_time delay; 131 132 if (phase == tlm::END_REQ || 133 (&trans == blockingRequest && phase == tlm::BEGIN_RESP)) { 134 sc_assert(&trans == blockingRequest); 135 blockingRequest = nullptr; 136 137 // Did another request arrive while blocked, schedule a retry. 138 if (needToSendRequestRetry) { 139 needToSendRequestRetry = false; 140 bsp.sendRetryReq(); 141 } 142 } 143 if (phase == tlm::BEGIN_RESP) { 144 auto &extension = Gem5SystemC::Gem5Extension::getExtension(trans); 145 auto packet = extension.getPacket(); 146 147 sc_assert(!blockingResponse); 148 149 bool need_retry = false; 150 151 /* 152 * If the packet was piped through and needs a response, we don't need 153 * to touch the packet and can forward it directly as a response. 154 * Otherwise, we need to make a response and send the transformed 155 * packet. 156 */ 157 if (extension.isPipeThrough()) { 158 if (packet->isResponse()) { 159 need_retry = !bsp.sendTimingResp(packet); 160 } 161 } else if (packet->needsResponse()) { 162 packet->makeResponse(); 163 need_retry = !bsp.sendTimingResp(packet); 164 } 165 166 if (need_retry) { 167 blockingResponse = &trans; 168 } else { 169 if (phase == tlm::BEGIN_RESP) { 170 // Send END_RESP and we're finished: 171 tlm::tlm_phase fw_phase = tlm::END_RESP; 172 sc_core::sc_time delay = sc_core::SC_ZERO_TIME; 173 socket->nb_transport_fw(trans, fw_phase, delay); 174 // Release the transaction with all the extensions. 175 trans.release(); 176 } 177 } 178 } 179 delete pe; 180} 181
|
| 182template <unsigned int BITWIDTH> 183MemBackdoorPtr 184Gem5ToTlmBridge<BITWIDTH>::getBackdoor(tlm::tlm_generic_payload &trans) 185{ 186 sc_dt::uint64 start = trans.get_address(); 187 sc_dt::uint64 end = start + trans.get_data_length(); 188 189 // Check for a back door we already know about. 190 AddrRange r(start, end); 191 auto it = backdoorMap.contains(r); 192 if (it != backdoorMap.end()) 193 return it->second; 194 195 // If not, ask the target for one. 196 tlm::tlm_dmi dmi_data; 197 if (!socket->get_direct_mem_ptr(trans, dmi_data)) 198 return nullptr; 199 200 // If the target gave us one, translate it to a gem5 MemBackdoor and 201 // store it in our cache. 202 AddrRange dmi_r(dmi_data.get_start_address(), dmi_data.get_end_address()); 203 auto backdoor = new MemBackdoor( 204 dmi_r, dmi_data.get_dmi_ptr(), MemBackdoor::NoAccess); 205 backdoor->readable(dmi_data.is_read_allowed()); 206 backdoor->writeable(dmi_data.is_write_allowed()); 207 208 backdoorMap.insert(dmi_r, backdoor); 209 210 return backdoor; 211} 212
|
169// Similar to TLM's blocking transport (LT) 170template <unsigned int BITWIDTH> 171Tick 172Gem5ToTlmBridge<BITWIDTH>::recvAtomic(PacketPtr packet) 173{ 174 panic_if(packet->cacheResponding(), 175 "Should not see packets where cache is responding"); 176
| 213// Similar to TLM's blocking transport (LT) 214template <unsigned int BITWIDTH> 215Tick 216Gem5ToTlmBridge<BITWIDTH>::recvAtomic(PacketPtr packet) 217{ 218 panic_if(packet->cacheResponding(), 219 "Should not see packets where cache is responding"); 220
|
177 panic_if(!(packet->isRead() || packet->isWrite()), 178 "Should only see read and writes at TLM memory\n");
| 221 // Prepare the transaction. 222 auto *trans = packet2payload(packet);
|
179 180 sc_core::sc_time delay = sc_core::SC_ZERO_TIME; 181
| 223 224 sc_core::sc_time delay = sc_core::SC_ZERO_TIME; 225
|
182 // Prepare the transaction. 183 tlm::tlm_generic_payload *trans = mm.allocate(); 184 trans->acquire(); 185 packet2payload(packet, *trans);
| 226 if (trans->get_command() != tlm::TLM_IGNORE_COMMAND) { 227 // Execute b_transport: 228 socket->b_transport(*trans, delay); 229 }
|
186
| 230
|
187 // Attach the packet pointer to the TLM transaction to keep track. 188 auto *extension = new Gem5SystemC::Gem5Extension(packet); 189 trans->set_auto_extension(extension);
| 231 if (packet->needsResponse()) 232 packet->makeResponse();
|
190
| 233
|
191 // Execute b_transport: 192 if (packet->cmd == MemCmd::SwapReq) { 193 SC_REPORT_FATAL("Gem5ToTlmBridge", "SwapReq not supported"); 194 } else if (packet->isRead()) {
| 234 trans->release(); 235 236 return delay.value(); 237} 238 239template <unsigned int BITWIDTH> 240Tick 241Gem5ToTlmBridge<BITWIDTH>::recvAtomicBackdoor( 242 PacketPtr packet, MemBackdoorPtr &backdoor) 243{ 244 panic_if(packet->cacheResponding(), 245 "Should not see packets where cache is responding"); 246 247 sc_core::sc_time delay = sc_core::SC_ZERO_TIME; 248 249 // Prepare the transaction. 250 auto *trans = packet2payload(packet); 251 252 if (trans->get_command() != tlm::TLM_IGNORE_COMMAND) { 253 // Execute b_transport:
|
195 socket->b_transport(*trans, delay);
| 254 socket->b_transport(*trans, delay);
|
196 } else if (packet->isInvalidate()) { 197 // do nothing 198 } else if (packet->isWrite()) { 199 socket->b_transport(*trans, delay);
| 255 // If the hint said we could use DMI, set that up. 256 if (trans->is_dmi_allowed()) 257 backdoor = getBackdoor(*trans);
|
200 } else {
| 258 } else {
|
201 SC_REPORT_FATAL("Gem5ToTlmBridge", "Typo of request not supported");
| 259 // There's no transaction to piggy back on, so just request the 260 // backdoor normally. 261 backdoor = getBackdoor(*trans);
|
202 } 203
| 262 } 263
|
204 if (packet->needsResponse()) {
| 264 if (packet->needsResponse())
|
205 packet->makeResponse();
| 265 packet->makeResponse();
|
206 }
| |
207 208 trans->release(); 209 210 return delay.value(); 211} 212 213template <unsigned int BITWIDTH> 214void 215Gem5ToTlmBridge<BITWIDTH>::recvFunctionalSnoop(PacketPtr packet) 216{ 217 // Snooping should be implemented with tlm_dbg_transport. 218 SC_REPORT_FATAL("Gem5ToTlmBridge", 219 "unimplemented func.: recvFunctionalSnoop"); 220} 221 222// Similar to TLM's non-blocking transport (AT). 223template <unsigned int BITWIDTH> 224bool 225Gem5ToTlmBridge<BITWIDTH>::recvTimingReq(PacketPtr packet) 226{ 227 panic_if(packet->cacheResponding(), 228 "Should not see packets where cache is responding"); 229 230 panic_if(!(packet->isRead() || packet->isWrite()), 231 "Should only see read and writes at TLM memory\n"); 232 233 234 // We should never get a second request after noting that a retry is 235 // required. 236 sc_assert(!needToSendRequestRetry); 237 238 // Remember if a request comes in while we're blocked so that a retry 239 // can be sent to gem5. 240 if (blockingRequest) { 241 needToSendRequestRetry = true; 242 return false; 243 } 244 245 /* 246 * NOTE: normal tlm is blocking here. But in our case we return false 247 * and tell gem5 when a retry can be done. This is the main difference 248 * in the protocol: 249 * if (requestInProgress) 250 * { 251 * wait(endRequestEvent); 252 * } 253 * requestInProgress = trans; 254 */ 255 256 // Prepare the transaction.
| 266 267 trans->release(); 268 269 return delay.value(); 270} 271 272template <unsigned int BITWIDTH> 273void 274Gem5ToTlmBridge<BITWIDTH>::recvFunctionalSnoop(PacketPtr packet) 275{ 276 // Snooping should be implemented with tlm_dbg_transport. 277 SC_REPORT_FATAL("Gem5ToTlmBridge", 278 "unimplemented func.: recvFunctionalSnoop"); 279} 280 281// Similar to TLM's non-blocking transport (AT). 282template <unsigned int BITWIDTH> 283bool 284Gem5ToTlmBridge<BITWIDTH>::recvTimingReq(PacketPtr packet) 285{ 286 panic_if(packet->cacheResponding(), 287 "Should not see packets where cache is responding"); 288 289 panic_if(!(packet->isRead() || packet->isWrite()), 290 "Should only see read and writes at TLM memory\n"); 291 292 293 // We should never get a second request after noting that a retry is 294 // required. 295 sc_assert(!needToSendRequestRetry); 296 297 // Remember if a request comes in while we're blocked so that a retry 298 // can be sent to gem5. 299 if (blockingRequest) { 300 needToSendRequestRetry = true; 301 return false; 302 } 303 304 /* 305 * NOTE: normal tlm is blocking here. But in our case we return false 306 * and tell gem5 when a retry can be done. This is the main difference 307 * in the protocol: 308 * if (requestInProgress) 309 * { 310 * wait(endRequestEvent); 311 * } 312 * requestInProgress = trans; 313 */ 314 315 // Prepare the transaction.
|
257 tlm::tlm_generic_payload *trans = mm.allocate(); 258 trans->acquire(); 259 packet2payload(packet, *trans);
| 316 auto *trans = packet2payload(packet);
|
260
| 317
|
261 // Attach the packet pointer to the TLM transaction to keep track. 262 auto *extension = new Gem5SystemC::Gem5Extension(packet); 263 trans->set_auto_extension(extension); 264
| |
265 /* 266 * Pay for annotated transport delays. 267 * 268 * The header delay marks the point in time, when the packet first is seen 269 * by the transactor. This is the point in time when the transactor needs 270 * to send the BEGIN_REQ to the SystemC world. 271 * 272 * NOTE: We drop the payload delay here. Normally, the receiver would be 273 * responsible for handling the payload delay. In this case, however, 274 * the receiver is a SystemC module and has no notion of the gem5 275 * transport protocol and we cannot simply forward the 276 * payload delay to the receiving module. Instead, we expect the 277 * receiving SystemC module to model the payload delay by deferring 278 * the END_REQ. This could lead to incorrect delays, if the XBar 279 * payload delay is longer than the time the receiver needs to accept 280 * the request (time between BEGIN_REQ and END_REQ). 281 * 282 * TODO: We could detect the case described above by remembering the 283 * payload delay and comparing it to the time between BEGIN_REQ and 284 * END_REQ. Then, a warning should be printed. 285 */ 286 auto delay = sc_core::sc_time::from_value(packet->payloadDelay); 287 // Reset the delays 288 packet->payloadDelay = 0; 289 packet->headerDelay = 0; 290 291 // Starting TLM non-blocking sequence (AT) Refer to IEEE1666-2011 SystemC 292 // Standard Page 507 for a visualisation of the procedure. 293 tlm::tlm_phase phase = tlm::BEGIN_REQ; 294 tlm::tlm_sync_enum status; 295 status = socket->nb_transport_fw(*trans, phase, delay); 296 // Check returned value: 297 if (status == tlm::TLM_ACCEPTED) { 298 sc_assert(phase == tlm::BEGIN_REQ); 299 // Accepted but is now blocking until END_REQ (exclusion rule). 300 blockingRequest = trans; 301 } else if (status == tlm::TLM_UPDATED) { 302 // The Timing annotation must be honored: 303 sc_assert(phase == tlm::END_REQ || phase == tlm::BEGIN_RESP); 304 305 auto *pe = new Gem5SystemC::PayloadEvent<Gem5ToTlmBridge>( 306 *this, &Gem5ToTlmBridge::pec, "PEQ"); 307 Tick nextEventTick = curTick() + delay.value(); 308 system->wakeupEventQueue(nextEventTick); 309 system->schedule(pe, nextEventTick); 310 } else if (status == tlm::TLM_COMPLETED) { 311 // Transaction is over nothing has do be done. 312 sc_assert(phase == tlm::END_RESP); 313 trans->release(); 314 } 315 316 return true; 317} 318 319template <unsigned int BITWIDTH> 320bool 321Gem5ToTlmBridge<BITWIDTH>::recvTimingSnoopResp(PacketPtr packet) 322{ 323 // Snooping should be implemented with tlm_dbg_transport. 324 SC_REPORT_FATAL("Gem5ToTlmBridge", 325 "unimplemented func.: recvTimingSnoopResp"); 326 return false; 327} 328 329template <unsigned int BITWIDTH> 330bool 331Gem5ToTlmBridge<BITWIDTH>::tryTiming(PacketPtr packet) 332{ 333 panic("tryTiming(PacketPtr) isn't implemented."); 334} 335 336template <unsigned int BITWIDTH> 337void 338Gem5ToTlmBridge<BITWIDTH>::recvRespRetry() 339{ 340 /* Retry a response */ 341 sc_assert(blockingResponse); 342 343 tlm::tlm_generic_payload *trans = blockingResponse; 344 blockingResponse = nullptr; 345 PacketPtr packet = 346 Gem5SystemC::Gem5Extension::getExtension(trans).getPacket(); 347 348 bool need_retry = !bsp.sendTimingResp(packet); 349 350 sc_assert(!need_retry); 351 352 sc_core::sc_time delay = sc_core::SC_ZERO_TIME; 353 tlm::tlm_phase phase = tlm::END_RESP; 354 socket->nb_transport_fw(*trans, phase, delay); 355 // Release transaction with all the extensions 356 trans->release(); 357} 358 359// Similar to TLM's debug transport. 360template <unsigned int BITWIDTH> 361void 362Gem5ToTlmBridge<BITWIDTH>::recvFunctional(PacketPtr packet) 363{ 364 // Prepare the transaction.
| 318 /* 319 * Pay for annotated transport delays. 320 * 321 * The header delay marks the point in time, when the packet first is seen 322 * by the transactor. This is the point in time when the transactor needs 323 * to send the BEGIN_REQ to the SystemC world. 324 * 325 * NOTE: We drop the payload delay here. Normally, the receiver would be 326 * responsible for handling the payload delay. In this case, however, 327 * the receiver is a SystemC module and has no notion of the gem5 328 * transport protocol and we cannot simply forward the 329 * payload delay to the receiving module. Instead, we expect the 330 * receiving SystemC module to model the payload delay by deferring 331 * the END_REQ. This could lead to incorrect delays, if the XBar 332 * payload delay is longer than the time the receiver needs to accept 333 * the request (time between BEGIN_REQ and END_REQ). 334 * 335 * TODO: We could detect the case described above by remembering the 336 * payload delay and comparing it to the time between BEGIN_REQ and 337 * END_REQ. Then, a warning should be printed. 338 */ 339 auto delay = sc_core::sc_time::from_value(packet->payloadDelay); 340 // Reset the delays 341 packet->payloadDelay = 0; 342 packet->headerDelay = 0; 343 344 // Starting TLM non-blocking sequence (AT) Refer to IEEE1666-2011 SystemC 345 // Standard Page 507 for a visualisation of the procedure. 346 tlm::tlm_phase phase = tlm::BEGIN_REQ; 347 tlm::tlm_sync_enum status; 348 status = socket->nb_transport_fw(*trans, phase, delay); 349 // Check returned value: 350 if (status == tlm::TLM_ACCEPTED) { 351 sc_assert(phase == tlm::BEGIN_REQ); 352 // Accepted but is now blocking until END_REQ (exclusion rule). 353 blockingRequest = trans; 354 } else if (status == tlm::TLM_UPDATED) { 355 // The Timing annotation must be honored: 356 sc_assert(phase == tlm::END_REQ || phase == tlm::BEGIN_RESP); 357 358 auto *pe = new Gem5SystemC::PayloadEvent<Gem5ToTlmBridge>( 359 *this, &Gem5ToTlmBridge::pec, "PEQ"); 360 Tick nextEventTick = curTick() + delay.value(); 361 system->wakeupEventQueue(nextEventTick); 362 system->schedule(pe, nextEventTick); 363 } else if (status == tlm::TLM_COMPLETED) { 364 // Transaction is over nothing has do be done. 365 sc_assert(phase == tlm::END_RESP); 366 trans->release(); 367 } 368 369 return true; 370} 371 372template <unsigned int BITWIDTH> 373bool 374Gem5ToTlmBridge<BITWIDTH>::recvTimingSnoopResp(PacketPtr packet) 375{ 376 // Snooping should be implemented with tlm_dbg_transport. 377 SC_REPORT_FATAL("Gem5ToTlmBridge", 378 "unimplemented func.: recvTimingSnoopResp"); 379 return false; 380} 381 382template <unsigned int BITWIDTH> 383bool 384Gem5ToTlmBridge<BITWIDTH>::tryTiming(PacketPtr packet) 385{ 386 panic("tryTiming(PacketPtr) isn't implemented."); 387} 388 389template <unsigned int BITWIDTH> 390void 391Gem5ToTlmBridge<BITWIDTH>::recvRespRetry() 392{ 393 /* Retry a response */ 394 sc_assert(blockingResponse); 395 396 tlm::tlm_generic_payload *trans = blockingResponse; 397 blockingResponse = nullptr; 398 PacketPtr packet = 399 Gem5SystemC::Gem5Extension::getExtension(trans).getPacket(); 400 401 bool need_retry = !bsp.sendTimingResp(packet); 402 403 sc_assert(!need_retry); 404 405 sc_core::sc_time delay = sc_core::SC_ZERO_TIME; 406 tlm::tlm_phase phase = tlm::END_RESP; 407 socket->nb_transport_fw(*trans, phase, delay); 408 // Release transaction with all the extensions 409 trans->release(); 410} 411 412// Similar to TLM's debug transport. 413template <unsigned int BITWIDTH> 414void 415Gem5ToTlmBridge<BITWIDTH>::recvFunctional(PacketPtr packet) 416{ 417 // Prepare the transaction.
|
365 tlm::tlm_generic_payload *trans = mm.allocate(); 366 trans->acquire(); 367 packet2payload(packet, *trans);
| 418 auto *trans = packet2payload(packet);
|
368
| 419
|
369 // Attach the packet pointer to the TLM transaction to keep track. 370 auto *extension = new Gem5SystemC::Gem5Extension(packet); 371 trans->set_auto_extension(extension); 372
| |
373 /* Execute Debug Transport: */ 374 unsigned int bytes = socket->transport_dbg(*trans); 375 if (bytes != trans->get_data_length()) { 376 SC_REPORT_FATAL("Gem5ToTlmBridge", 377 "debug transport was not completed"); 378 } 379 380 trans->release(); 381} 382 383template <unsigned int BITWIDTH> 384tlm::tlm_sync_enum 385Gem5ToTlmBridge<BITWIDTH>::nb_transport_bw(tlm::tlm_generic_payload &trans, 386 tlm::tlm_phase &phase, sc_core::sc_time &delay) 387{ 388 auto *pe = new Gem5SystemC::PayloadEvent<Gem5ToTlmBridge>( 389 *this, &Gem5ToTlmBridge::pec, "PE"); 390 Tick nextEventTick = curTick() + delay.value(); 391 system->wakeupEventQueue(nextEventTick); 392 system->schedule(pe, nextEventTick); 393 return tlm::TLM_ACCEPTED; 394} 395 396template <unsigned int BITWIDTH>
| 420 /* Execute Debug Transport: */ 421 unsigned int bytes = socket->transport_dbg(*trans); 422 if (bytes != trans->get_data_length()) { 423 SC_REPORT_FATAL("Gem5ToTlmBridge", 424 "debug transport was not completed"); 425 } 426 427 trans->release(); 428} 429 430template <unsigned int BITWIDTH> 431tlm::tlm_sync_enum 432Gem5ToTlmBridge<BITWIDTH>::nb_transport_bw(tlm::tlm_generic_payload &trans, 433 tlm::tlm_phase &phase, sc_core::sc_time &delay) 434{ 435 auto *pe = new Gem5SystemC::PayloadEvent<Gem5ToTlmBridge>( 436 *this, &Gem5ToTlmBridge::pec, "PE"); 437 Tick nextEventTick = curTick() + delay.value(); 438 system->wakeupEventQueue(nextEventTick); 439 system->schedule(pe, nextEventTick); 440 return tlm::TLM_ACCEPTED; 441} 442 443template <unsigned int BITWIDTH>
|
| 444void 445Gem5ToTlmBridge<BITWIDTH>::invalidate_direct_mem_ptr( 446 sc_dt::uint64 start_range, sc_dt::uint64 end_range) 447{ 448 AddrRange r(start_range, end_range); 449 450 for (;;) { 451 auto it = backdoorMap.intersects(r); 452 if (it == backdoorMap.end()) 453 break; 454 455 it->second->invalidate(); 456 delete it->second; 457 backdoorMap.erase(it); 458 }; 459} 460 461template <unsigned int BITWIDTH>
|
397Gem5ToTlmBridge<BITWIDTH>::Gem5ToTlmBridge( 398 Params *params, const sc_core::sc_module_name &mn) : 399 Gem5ToTlmBridgeBase(mn), bsp(std::string(name()) + ".gem5", *this), 400 socket("tlm_socket"), 401 wrapper(socket, std::string(name()) + ".tlm", InvalidPortID), 402 system(params->system), blockingRequest(nullptr), 403 needToSendRequestRetry(false), blockingResponse(nullptr), 404 addrRanges(params->addr_ranges.begin(), params->addr_ranges.end()) 405{ 406} 407 408template <unsigned int BITWIDTH> 409::Port & 410Gem5ToTlmBridge<BITWIDTH>::gem5_getPort(const std::string &if_name, int idx) 411{ 412 if (if_name == "gem5") 413 return bsp; 414 else if (if_name == "tlm") 415 return wrapper; 416 417 return sc_core::sc_module::gem5_getPort(if_name, idx); 418} 419 420template <unsigned int BITWIDTH> 421void 422Gem5ToTlmBridge<BITWIDTH>::before_end_of_elaboration() 423{ 424 bsp.sendRangeChange(); 425 426 socket.register_nb_transport_bw(this, &Gem5ToTlmBridge::nb_transport_bw);
| 462Gem5ToTlmBridge<BITWIDTH>::Gem5ToTlmBridge( 463 Params *params, const sc_core::sc_module_name &mn) : 464 Gem5ToTlmBridgeBase(mn), bsp(std::string(name()) + ".gem5", *this), 465 socket("tlm_socket"), 466 wrapper(socket, std::string(name()) + ".tlm", InvalidPortID), 467 system(params->system), blockingRequest(nullptr), 468 needToSendRequestRetry(false), blockingResponse(nullptr), 469 addrRanges(params->addr_ranges.begin(), params->addr_ranges.end()) 470{ 471} 472 473template <unsigned int BITWIDTH> 474::Port & 475Gem5ToTlmBridge<BITWIDTH>::gem5_getPort(const std::string &if_name, int idx) 476{ 477 if (if_name == "gem5") 478 return bsp; 479 else if (if_name == "tlm") 480 return wrapper; 481 482 return sc_core::sc_module::gem5_getPort(if_name, idx); 483} 484 485template <unsigned int BITWIDTH> 486void 487Gem5ToTlmBridge<BITWIDTH>::before_end_of_elaboration() 488{ 489 bsp.sendRangeChange(); 490 491 socket.register_nb_transport_bw(this, &Gem5ToTlmBridge::nb_transport_bw);
|
| 492 socket.register_invalidate_direct_mem_ptr( 493 this, &Gem5ToTlmBridge::invalidate_direct_mem_ptr);
|
427 sc_core::sc_module::before_end_of_elaboration(); 428} 429 430} // namespace sc_gem5 431 432sc_gem5::Gem5ToTlmBridge<32> * 433Gem5ToTlmBridge32Params::create() 434{ 435 return new sc_gem5::Gem5ToTlmBridge<32>( 436 this, sc_core::sc_module_name(name.c_str())); 437} 438 439sc_gem5::Gem5ToTlmBridge<64> * 440Gem5ToTlmBridge64Params::create() 441{ 442 return new sc_gem5::Gem5ToTlmBridge<64>( 443 this, sc_core::sc_module_name(name.c_str())); 444}
| 494 sc_core::sc_module::before_end_of_elaboration(); 495} 496 497} // namespace sc_gem5 498 499sc_gem5::Gem5ToTlmBridge<32> * 500Gem5ToTlmBridge32Params::create() 501{ 502 return new sc_gem5::Gem5ToTlmBridge<32>( 503 this, sc_core::sc_module_name(name.c_str())); 504} 505 506sc_gem5::Gem5ToTlmBridge<64> * 507Gem5ToTlmBridge64Params::create() 508{ 509 return new sc_gem5::Gem5ToTlmBridge<64>( 510 this, sc_core::sc_module_name(name.c_str())); 511}
|