From 5d35e225181372f559c78a0a168017bd47af00ed Mon Sep 17 00:00:00 2001 From: Yu-hsin Wang Date: Thu, 22 Sep 2022 10:51:21 +0800 Subject: [PATCH] systemc: gem5_to_tlm bridge should reuse existed tlm payload Given a data path initiated from SystemC, routed by gem5, and handled by SystemC finally. SystemC -> gem5 -> SystemC The target SystemC needs to get the original transaction object. Otherwise, it would lose the extensions in the payload. To fix the issue, we moves the SenderState class to public for reachibility. After that, we refactor the logic converting between payload and packet to make sure they can use the correct instance. Finally, we fix the potential address change during routing. Change-Id: Ic6d24e98454f564f7dd6b43ad8c011e1ea7ea433 Reviewed-on: https://gem5-review.googlesource.com/c/public/gem5/+/63771 Tested-by: kokoro Reviewed-by: Gabe Black Maintainer: Gabe Black --- src/systemc/tlm_bridge/gem5_to_tlm.cc | 22 ++++++- src/systemc/tlm_bridge/sc_ext.hh | 6 ++ src/systemc/tlm_bridge/tlm_to_gem5.cc | 92 ++++++++++----------------- src/systemc/tlm_bridge/tlm_to_gem5.hh | 9 +-- 4 files changed, 62 insertions(+), 67 deletions(-) diff --git a/src/systemc/tlm_bridge/gem5_to_tlm.cc b/src/systemc/tlm_bridge/gem5_to_tlm.cc index 37da822499..6f17a8b0aa 100644 --- a/src/systemc/tlm_bridge/gem5_to_tlm.cc +++ b/src/systemc/tlm_bridge/gem5_to_tlm.cc @@ -121,13 +121,29 @@ addPacketToPayloadConversionStep(PacketToPayloadConversionStep step) } /** - * Convert a gem5 packet to a TLM payload by copying all the relevant - * information to new tlm payload. + * Convert a gem5 packet to TLM payload by copying all the relevant information + * to new payload. If the transaction is initiated by TLM model, we would use + * the original payload. + * The return value is the payload pointer. */ tlm::tlm_generic_payload * packet2payload(PacketPtr packet) { - tlm::tlm_generic_payload *trans = mm.allocate(); + tlm::tlm_generic_payload *trans = nullptr; + auto *tlmSenderState = + packet->findNextSenderState(); + + // If there is a SenderState, we can pipe through the original transaction. + // Otherwise, we generate a new transaction based on the packet. + if (tlmSenderState != nullptr) { + // Sync the address which could have changed. + trans = &tlmSenderState->trans; + trans->set_address(packet->getAddr()); + trans->acquire(); + return trans; + } + + trans = mm.allocate(); trans->acquire(); trans->set_address(packet->getAddr()); diff --git a/src/systemc/tlm_bridge/sc_ext.hh b/src/systemc/tlm_bridge/sc_ext.hh index 3f7c3204f5..bb676761ce 100644 --- a/src/systemc/tlm_bridge/sc_ext.hh +++ b/src/systemc/tlm_bridge/sc_ext.hh @@ -44,6 +44,12 @@ namespace Gem5SystemC { +struct TlmSenderState : public gem5::Packet::SenderState +{ + tlm::tlm_generic_payload &trans; + TlmSenderState(tlm::tlm_generic_payload &trans) : trans(trans) {} +}; + class Gem5Extension: public tlm::tlm_extension { public: diff --git a/src/systemc/tlm_bridge/tlm_to_gem5.cc b/src/systemc/tlm_bridge/tlm_to_gem5.cc index 9f7c6eb96f..4cb8194086 100644 --- a/src/systemc/tlm_bridge/tlm_to_gem5.cc +++ b/src/systemc/tlm_bridge/tlm_to_gem5.cc @@ -97,9 +97,29 @@ addPayloadToPacketConversionStep(PayloadToPacketConversionStep step) extraPayloadToPacketSteps.push_back(std::move(step)); } -PacketPtr +/** + * Convert a TLM payload to gem5 packet by copying all the relevant information + * to new packet. If the transaction is initiated by gem5 model, we would use + * the original packet. + * The first return value is the packet pointer. + * The second return value is if the packet is newly created. + */ +std::pair payload2packet(RequestorID _id, tlm::tlm_generic_payload &trans) { + Gem5SystemC::Gem5Extension *extension = nullptr; + trans.get_extension(extension); + + // If there is an extension, this transaction was initiated by the gem5 + // world and we can pipe through the original packet. Otherwise, we + // generate a new packet based on the transaction. + if (extension != nullptr) { + auto pkt = extension->getPacket(); + // Sync the address which could have changed. + pkt->setAddr(trans.get_address()); + return std::make_pair(pkt, false); + } + MemCmd cmd; RequestPtr req; @@ -126,7 +146,7 @@ payload2packet(RequestorID _id, tlm::tlm_generic_payload &trans) cmd = MemCmd::WriteReq; break; case tlm::TLM_IGNORE_COMMAND: - return nullptr; + return std::make_pair(nullptr, false); default: SC_REPORT_FATAL("TlmToGem5Bridge", "received transaction with unsupported " @@ -150,7 +170,7 @@ payload2packet(RequestorID _id, tlm::tlm_generic_payload &trans) step(pkt, trans); } - return pkt; + return std::make_pair(pkt, true); } template @@ -198,21 +218,8 @@ TlmToGem5Bridge::handleBeginReq(tlm::tlm_generic_payload &trans) trans.acquire(); - PacketPtr pkt = nullptr; - - Gem5SystemC::Gem5Extension *extension = nullptr; - trans.get_extension(extension); - - // If there is an extension, this transaction was initiated by the gem5 - // world and we can pipe through the original packet. Otherwise, we - // generate a new packet based on the transaction. - if (extension != nullptr) { - pkt = extension->getPacket(); - } else { - pkt = payload2packet(_id, trans); - } - - auto tlmSenderState = new TlmSenderState(trans); + auto [pkt, pkt_created] = payload2packet(_id, trans); + auto *tlmSenderState = new Gem5SystemC::TlmSenderState(trans); pkt->pushSenderState(tlmSenderState); // If the packet doesn't need a response, we should send BEGIN_RESP by @@ -323,18 +330,7 @@ void TlmToGem5Bridge::b_transport(tlm::tlm_generic_payload &trans, sc_core::sc_time &t) { - Gem5SystemC::Gem5Extension *extension = nullptr; - trans.get_extension(extension); - - PacketPtr pkt = nullptr; - - // If there is an extension, this transaction was initiated by the gem5 - // world and we can pipe through the original packet. - if (extension != nullptr) { - pkt = extension->getPacket(); - } else { - pkt = payload2packet(_id, trans); - } + auto [pkt, pkt_created] = payload2packet(_id, trans); MemBackdoorPtr backdoor = nullptr; Tick ticks = bmp.sendAtomicBackdoor(pkt, backdoor); @@ -352,7 +348,7 @@ TlmToGem5Bridge::b_transport(tlm::tlm_generic_payload &trans, // update time t += delay; - if (extension == nullptr) + if (pkt_created) destroyPacket(pkt); trans.set_response_status(tlm::TLM_OK_RESPONSE); @@ -362,19 +358,12 @@ template unsigned int TlmToGem5Bridge::transport_dbg(tlm::tlm_generic_payload &trans) { - Gem5SystemC::Gem5Extension *extension = nullptr; - trans.get_extension(extension); + auto [pkt, pkt_created] = payload2packet(_id, trans); + if (pkt != nullptr) { + bmp.sendFunctional(pkt); - // If there is an extension, this transaction was initiated by the gem5 - // world and we can pipe through the original packet. - if (extension != nullptr) { - bmp.sendFunctional(extension->getPacket()); - } else { - auto pkt = payload2packet(_id, trans); - if (pkt) { - bmp.sendFunctional(pkt); + if (pkt_created) destroyPacket(pkt); - } } return trans.get_data_length(); @@ -385,19 +374,7 @@ bool TlmToGem5Bridge::get_direct_mem_ptr(tlm::tlm_generic_payload &trans, tlm::tlm_dmi &dmi_data) { - Gem5SystemC::Gem5Extension *extension = nullptr; - trans.get_extension(extension); - - PacketPtr pkt = nullptr; - - // If there is an extension, this transaction was initiated by the gem5 - // world and we can pipe through the original packet. - if (extension != nullptr) { - pkt = extension->getPacket(); - } else { - pkt = payload2packet(_id, trans); - pkt->req->setFlags(Request::NO_ACCESS); - } + auto [pkt, pkt_created] = payload2packet(_id, trans); MemBackdoorPtr backdoor = nullptr; bmp.sendAtomicBackdoor(pkt, backdoor); @@ -423,7 +400,7 @@ TlmToGem5Bridge::get_direct_mem_ptr(tlm::tlm_generic_payload &trans, ); } - if (extension == nullptr) + if (!pkt_created) destroyPacket(pkt); trans.set_response_status(tlm::TLM_OK_RESPONSE); @@ -455,7 +432,8 @@ TlmToGem5Bridge::recvTimingResp(PacketPtr pkt) pkt->payloadDelay = 0; pkt->headerDelay = 0; - auto tlmSenderState = dynamic_cast(pkt->popSenderState()); + auto *tlmSenderState = + dynamic_cast(pkt->popSenderState()); sc_assert(tlmSenderState != nullptr); auto &trans = tlmSenderState->trans; diff --git a/src/systemc/tlm_bridge/tlm_to_gem5.hh b/src/systemc/tlm_bridge/tlm_to_gem5.hh index b0fe62af08..e452d8b26b 100644 --- a/src/systemc/tlm_bridge/tlm_to_gem5.hh +++ b/src/systemc/tlm_bridge/tlm_to_gem5.hh @@ -59,6 +59,7 @@ #define __SYSTEMC_TLM_BRIDGE_TLM_TO_GEM5_HH__ #include +#include #include "mem/port.hh" #include "params/TlmToGem5BridgeBase.hh" @@ -78,7 +79,7 @@ using PayloadToPacketConversionStep = void addPayloadToPacketConversionStep(PayloadToPacketConversionStep step); -gem5::PacketPtr payload2packet(gem5::RequestorID _id, +std::pair payload2packet(gem5::RequestorID _id, tlm::tlm_generic_payload &trans); class TlmToGem5BridgeBase : public sc_core::sc_module @@ -91,12 +92,6 @@ template class TlmToGem5Bridge : public TlmToGem5BridgeBase { private: - struct TlmSenderState : public gem5::Packet::SenderState - { - tlm::tlm_generic_payload &trans; - TlmSenderState(tlm::tlm_generic_payload &trans) : trans(trans) {} - }; - class BridgeRequestPort : public gem5::RequestPort { protected: