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 <noreply+kokoro@google.com> Reviewed-by: Gabe Black <gabe.black@gmail.com> Maintainer: Gabe Black <gabe.black@gmail.com>
This commit is contained in:
@@ -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<Gem5SystemC::TlmSenderState>();
|
||||
|
||||
// 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());
|
||||
|
||||
@@ -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<Gem5Extension>
|
||||
{
|
||||
public:
|
||||
|
||||
@@ -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<PacketPtr, bool>
|
||||
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 <unsigned int BITWIDTH>
|
||||
@@ -198,21 +218,8 @@ TlmToGem5Bridge<BITWIDTH>::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<BITWIDTH>::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<BITWIDTH>::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 BITWIDTH>
|
||||
unsigned int
|
||||
TlmToGem5Bridge<BITWIDTH>::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<BITWIDTH>::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<BITWIDTH>::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<BITWIDTH>::recvTimingResp(PacketPtr pkt)
|
||||
pkt->payloadDelay = 0;
|
||||
pkt->headerDelay = 0;
|
||||
|
||||
auto tlmSenderState = dynamic_cast<TlmSenderState*>(pkt->popSenderState());
|
||||
auto *tlmSenderState =
|
||||
dynamic_cast<Gem5SystemC::TlmSenderState*>(pkt->popSenderState());
|
||||
sc_assert(tlmSenderState != nullptr);
|
||||
|
||||
auto &trans = tlmSenderState->trans;
|
||||
|
||||
@@ -59,6 +59,7 @@
|
||||
#define __SYSTEMC_TLM_BRIDGE_TLM_TO_GEM5_HH__
|
||||
|
||||
#include <functional>
|
||||
#include <utility>
|
||||
|
||||
#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<gem5::PacketPtr, bool> payload2packet(gem5::RequestorID _id,
|
||||
tlm::tlm_generic_payload &trans);
|
||||
|
||||
class TlmToGem5BridgeBase : public sc_core::sc_module
|
||||
@@ -91,12 +92,6 @@ template <unsigned int BITWIDTH>
|
||||
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:
|
||||
|
||||
Reference in New Issue
Block a user