summaryrefslogtreecommitdiff
path: root/util/tlm/sc_master_port.cc
diff options
context:
space:
mode:
authorChristian Menard <Christian.Menard@tu-dresden.de>2017-02-09 19:15:43 -0500
committerChristian Menard <Christian.Menard@tu-dresden.de>2017-02-09 19:15:43 -0500
commitb5045005de6747a5247deb13af9974cfc6b73b08 (patch)
treeab4c38e4cccfd6a5e1dd9735ce95f226071f9eef /util/tlm/sc_master_port.cc
parent03f740664bc8db8890359c9c5ad02df9db478bae (diff)
downloadgem5-b5045005de6747a5247deb13af9974cfc6b73b08.tar.xz
misc: Clean up and complete the gem5<->SystemC-TLM bridge [7/10]
The current TLM bridge only provides a Slave Port that allows the gem5 world to send request to the SystemC world. This patch series refractors and cleans up the existing code, and adds a Master Port that allows the SystemC world to send requests to the gem5 world. This patch: * Implement 'pipe through' for gem5 Packets (see explanation below) Basically, this patch ensures that all transactions that originated in the gem5 world are converted back to the original packet when entering the gem5 world. So far, this only worked for packets that are responded to by a SyctemC component (e.g. when a gem5 CPU sends a request to a SystemC memory). By implementing the 'pipe through' this patch ensures, that packets that are responded to by a gem5 component (e.g. when a gem5 CPU sends a request to a gem5 memory via a SystemC interconnect) are handled properly. Reviewed at http://reviews.gem5.org/r/3796/ Signed-off-by: Jason Lowe-Power <jason@lowepower.com>
Diffstat (limited to 'util/tlm/sc_master_port.cc')
-rw-r--r--util/tlm/sc_master_port.cc90
1 files changed, 74 insertions, 16 deletions
diff --git a/util/tlm/sc_master_port.cc b/util/tlm/sc_master_port.cc
index 4ab1f51c6..5f3950260 100644
--- a/util/tlm/sc_master_port.cc
+++ b/util/tlm/sc_master_port.cc
@@ -36,6 +36,7 @@
#include "master_transactor.hh"
#include "params/ExternalMaster.hh"
+#include "sc_ext.hh"
#include "sc_master_port.hh"
#include "sim/system.hh"
@@ -87,6 +88,7 @@ SCMasterPort::SCMasterPort(const std::string& name_,
peq(this, &SCMasterPort::peq_cb),
waitForRetry(false),
pendingRequest(nullptr),
+ pendingPacket(nullptr),
needToSendRetry(false),
responseInProgress(false),
transactor(nullptr),
@@ -158,6 +160,7 @@ SCMasterPort::nb_transport_fw(tlm::tlm_generic_payload& trans,
}
// ... and queue the valid transaction
+ trans.acquire();
peq.notify(trans, phase, delay);
return tlm::TLM_ACCEPTED;
}
@@ -191,18 +194,35 @@ SCMasterPort::handleBeginReq(tlm::tlm_generic_payload& trans)
{
sc_assert(!waitForRetry);
sc_assert(pendingRequest == nullptr);
+ sc_assert(pendingPacket == nullptr);
trans.acquire();
- auto pkt = generatePacket(trans);
+
+ PacketPtr pkt = nullptr;
+
+ 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) {
+ extension->setPipeThrough();
+ pkt = extension->getPacket();
+ } else {
+ pkt = generatePacket(trans);
+ }
auto tlmSenderState = new TlmSenderState(trans);
pkt->pushSenderState(tlmSenderState);
if (sendTimingReq(pkt)) { // port is free -> send END_REQ immediately
sendEndReq(trans);
+ trans.release();
} else { // port is blocked -> wait for retry before sending END_REQ
waitForRetry = true;
pendingRequest = &trans;
+ pendingPacket = pkt;
}
}
@@ -236,11 +256,25 @@ void
SCMasterPort::b_transport(tlm::tlm_generic_payload& trans,
sc_core::sc_time& t)
{
- auto pkt = generatePacket(trans);
+ 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) {
+ extension->setPipeThrough();
+ pkt = extension->getPacket();
+ } else {
+ pkt = generatePacket(trans);
+ }
- // send an atomic request to gem5
Tick ticks = sendAtomic(pkt);
- panic_if(!pkt->isResponse(), "Packet sending failed!\n");
+
+ // send an atomic request to gem5
+ panic_if(pkt->needsResponse() && !pkt->isResponse(),
+ "Packet sending failed!\n");
// one tick is a pico second
auto delay =
@@ -249,7 +283,8 @@ SCMasterPort::b_transport(tlm::tlm_generic_payload& trans,
// update time
t += delay;
- destroyPacket(pkt);
+ if (extension != nullptr)
+ destroyPacket(pkt);
trans.set_response_status(tlm::TLM_OK_RESPONSE);
}
@@ -257,11 +292,19 @@ SCMasterPort::b_transport(tlm::tlm_generic_payload& trans,
unsigned int
SCMasterPort::transport_dbg(tlm::tlm_generic_payload& trans)
{
- auto pkt = generatePacket(trans);
-
- sendFunctional(pkt);
-
- destroyPacket(pkt);
+ 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.
+ if (extension != nullptr) {
+ extension->setPipeThrough();
+ sendFunctional(extension->getPacket());
+ } else {
+ auto pkt = generatePacket(trans);
+ sendFunctional(pkt);
+ destroyPacket(pkt);
+ }
return trans.get_data_length();
}
@@ -291,11 +334,22 @@ SCMasterPort::recvTimingResp(PacketPtr pkt)
sc_core::sc_time::from_value(pkt->payloadDelay + pkt->headerDelay);
auto tlmSenderState = dynamic_cast<TlmSenderState*>(pkt->popSenderState());
+ sc_assert(tlmSenderState != nullptr);
+
auto& trans = tlmSenderState->trans;
+ Gem5Extension* extension = nullptr;
+ trans.get_extension(extension);
+
// clean up
delete tlmSenderState;
- destroyPacket(pkt);
+
+ // If there is an extension the packet was piped through and we must not
+ // delete it. The packet travels back with the transaction.
+ if (extension == nullptr)
+ destroyPacket(pkt);
+ else
+ sc_assert(extension->isPipeThrough());
sendBeginResp(trans, delay);
trans.release();
@@ -330,14 +384,18 @@ SCMasterPort::recvReqRetry()
{
sc_assert(waitForRetry);
sc_assert(pendingRequest != nullptr);
+ sc_assert(pendingPacket != nullptr);
- auto& trans = *pendingRequest;
+ if (sendTimingReq(pendingPacket)) {
+ waitForRetry = false;
+ pendingPacket = nullptr;
- waitForRetry = false;
- pendingRequest = nullptr;
+ auto& trans = *pendingRequest;
+ sendEndReq(trans);
+ trans.release();
- // retry
- handleBeginReq(trans);
+ pendingRequest = nullptr;
+ }
}
void