From eb265f4bdd18581a20e580bca5ba1ce8d3e45f54 Mon Sep 17 00:00:00 2001 From: Lukas Steiner Date: Thu, 30 Apr 2020 11:30:47 +0200 Subject: [PATCH] Removed arbiter's send methods to implement early completion. --- DRAMSys/library/src/controller/Controller.cpp | 4 +- DRAMSys/library/src/simulation/Arbiter.cpp | 89 ++++++++++--------- DRAMSys/library/src/simulation/Arbiter.h | 8 +- 3 files changed, 51 insertions(+), 50 deletions(-) diff --git a/DRAMSys/library/src/controller/Controller.cpp b/DRAMSys/library/src/controller/Controller.cpp index 8a80ca9d..dfaf36fc 100644 --- a/DRAMSys/library/src/controller/Controller.cpp +++ b/DRAMSys/library/src/controller/Controller.cpp @@ -333,18 +333,16 @@ void Controller::controllerMethod() tlm_sync_enum Controller::nb_transport_fw(tlm_generic_payload &trans, tlm_phase &phase, sc_time &delay) { - sc_time notificationDelay = delay; + sc_time notificationDelay = delay + Configuration::getInstance().memSpec->tCK; if (phase == BEGIN_REQ) { - notificationDelay += Configuration::getInstance().memSpec->tCK; payloadToAcquire = &trans; timeToAcquire = sc_time_stamp() + notificationDelay; beginReqEvent.notify(notificationDelay); } else if (phase = END_RESP) { - notificationDelay += Configuration::getInstance().memSpec->tCK; timeToRelease = sc_time_stamp() + notificationDelay; endRespEvent.notify(notificationDelay); } diff --git a/DRAMSys/library/src/simulation/Arbiter.cpp b/DRAMSys/library/src/simulation/Arbiter.cpp index 73810df7..01234602 100644 --- a/DRAMSys/library/src/simulation/Arbiter.cpp +++ b/DRAMSys/library/src/simulation/Arbiter.cpp @@ -76,6 +76,7 @@ tlm_sync_enum Arbiter::nb_transport_fw(int id, tlm_generic_payload &payload, if (phase == BEGIN_REQ) { + // TODO: do not adjust address permanently // adjust address offset: payload.set_address(payload.get_address() - Configuration::getInstance().addressOffset); @@ -103,8 +104,7 @@ tlm_sync_enum Arbiter::nb_transport_bw(int channelId, tlm_generic_payload &paylo tlm_phase &phase, sc_time &bwDelay) { // Check channel ID - if ((unsigned int)channelId != DramExtension::getExtension(payload).getChannel().ID()) - SC_REPORT_FATAL("Arbiter", "Payload extension was corrupted"); + assert((unsigned int)channelId == DramExtension::getExtension(payload).getChannel().ID()); PRINTDEBUGMESSAGE(name(), "[bw] " + phaseNameToString(phase) + " notification in " + bwDelay.to_string()); @@ -124,39 +124,51 @@ unsigned int Arbiter::transport_dbg(int /*id*/, tlm::tlm_generic_payload &trans) void Arbiter::peqCallback(tlm_generic_payload &payload, const tlm_phase &phase) { - unsigned int initiatorSocket = DramExtension::getExtension( - payload).getThread().ID(); + unsigned int threadId = DramExtension::getExtension(payload).getThread().ID(); unsigned int channelId = DramExtension::getExtension(payload).getChannel().ID(); - // Check the valid range of initiatorSocket ID and channel Id - // TODO: initiatorSocket ID not checked + // Check the valid range of thread ID and channel Id + // TODO: thread ID not checked assert(channelId < Configuration::getInstance().numberOfMemChannels); // Phases initiated by the intiator side from arbiter's point of view (devices performing memory requests to the arbiter) if (phase == BEGIN_REQ) { - if (channelIsFree[channelId]) { + if (channelIsFree[channelId]) + { // This channel was available. Forward the new transaction to the memory controller. channelIsFree[channelId] = false; - sendToChannel(channelId, payload, phase, SC_ZERO_TIME); - } else { + tlm_phase tPhase = phase; + sc_time tDelay = SC_ZERO_TIME; + iSocket[channelId]->nb_transport_fw(payload, tPhase, tDelay); + // TODO: early completion of channel controller!!! + } + else + { // This channel is busy. Enqueue the new transaction which phase is BEGIN_REQ. pendingRequests[channelId].push(&payload); } } // Phases initiated by the target side from arbiter's point of view (memory side) - else if (phase == END_REQ) { + else if (phase == END_REQ) + { channelIsFree[channelId] = true; // The arbiter receives a transaction which phase is END_REQ from memory controller and forwards it to the requester device. - sendToInitiator(initiatorSocket, payload, phase, SC_ZERO_TIME); + tlm_phase tPhase = phase; + sc_time tDelay = SC_ZERO_TIME; + tSocket[threadId]->nb_transport_bw(payload, tPhase, tDelay); // This channel is now free! Dispatch a new transaction (phase is BEGIN_REQ) from the queue, if any. Send it to the memory controller. - if (!pendingRequests[channelId].empty()) { - tlm_generic_payload *payloadToSend = pendingRequests[channelId].front(); - pendingRequests[channelId].pop(); + if (!pendingRequests[channelId].empty()) + { // Send ONE of the enqueued new transactions (phase is BEGIN_REQ) through this channel. - sendToChannel(channelId, *payloadToSend, BEGIN_REQ, SC_ZERO_TIME); + tlm_generic_payload &payloadToSend = *pendingRequests[channelId].front(); + pendingRequests[channelId].pop(); + tlm_phase tPhase = BEGIN_REQ; + sc_time tDelay = SC_ZERO_TIME; + iSocket[channelId]->nb_transport_fw(payloadToSend, tPhase, tDelay); + // TODO: early completion of channel controller // Mark the channel as busy again. channelIsFree[channelId] = false; } @@ -166,26 +178,39 @@ void Arbiter::peqCallback(tlm_generic_payload &payload, const tlm_phase &phase) // The arbiter receives a transaction in BEGIN_RESP phase // (that came from the memory side) and forwards it to the requester // device - if (receivedResponses[initiatorSocket].empty()) { - sendToInitiator(initiatorSocket, payload, phase, SC_ZERO_TIME); + if (pendingResponses[threadId].empty()) + { + tlm_phase tPhase = phase; + sc_time tDelay = SC_ZERO_TIME; + tSocket[threadId]->nb_transport_bw(payload, tPhase, tDelay); + // TODO: early completion of initiator!!! } + // Enqueue the transaction in BEGIN_RESP phase until the initiator - // device acknowledge it (phase changes to END_RESP). - receivedResponses[initiatorSocket].push(&payload); + // device acknowledges it (phase changes to END_RESP). + pendingResponses[threadId].push(&payload); } else if (phase == END_RESP) { // Send the END_RESP message to the memory - sendToChannel(channelId, payload, phase, SC_ZERO_TIME); + { + tlm_phase tPhase = phase; + sc_time tDelay = SC_ZERO_TIME; + iSocket[channelId]->nb_transport_fw(payload, tPhase, tDelay); + } // Drop one element of the queue of BEGIN_RESP from memory to this device - receivedResponses[initiatorSocket].pop(); + pendingResponses[threadId].pop(); // Check if there are queued transactoins with phase BEGIN_RESP from memory to this device - if (!receivedResponses[initiatorSocket].empty()) { + if (!pendingResponses[threadId].empty()) + { // The queue is not empty. - tlm_generic_payload *payloadToSend = receivedResponses[initiatorSocket].front(); + tlm_generic_payload &payloadToSend = *pendingResponses[threadId].front(); // Send ONE extra BEGIN_RESP to the device - sendToInitiator(initiatorSocket, *payloadToSend, BEGIN_RESP, SC_ZERO_TIME); + tlm_phase tPhase = BEGIN_RESP; + sc_time tDelay = SC_ZERO_TIME; + tSocket[threadId]->nb_transport_bw(payloadToSend, tPhase, tDelay); + // TODO: early completion of initiator!!! } } else @@ -193,22 +218,6 @@ void Arbiter::peqCallback(tlm_generic_payload &payload, const tlm_phase &phase) "Payload event queue in arbiter was triggered with unknown phase"); } -void Arbiter::sendToChannel(unsigned int channelId, tlm_generic_payload &payload, - const tlm_phase &phase, const sc_time &delay) -{ - tlm_phase TPhase = phase; - sc_time TDelay = delay; - iSocket[channelId]->nb_transport_fw(payload, TPhase, TDelay); -} - -void Arbiter::sendToInitiator(unsigned int id, tlm_generic_payload &payload, - const tlm_phase &phase, const sc_time &delay) -{ - tlm_phase TPhase = phase; - sc_time TDelay = delay; - tSocket[id]->nb_transport_bw(payload, TPhase, TDelay); -} - void Arbiter::appendDramExtension(int socketId, tlm_generic_payload &payload) { // Append Generation Extension diff --git a/DRAMSys/library/src/simulation/Arbiter.h b/DRAMSys/library/src/simulation/Arbiter.h index 2e0ab39d..1bb12de7 100644 --- a/DRAMSys/library/src/simulation/Arbiter.h +++ b/DRAMSys/library/src/simulation/Arbiter.h @@ -71,7 +71,7 @@ private: std::vector> pendingRequests; // used to account for the response_accept_delay in the initiators (traceplayer, core etc.) // This is a queue of responses comming from the memory side. The phase of these transactions is BEGIN_RESP. - std::map> receivedResponses; + std::map> pendingResponses; // Initiated by initiator side // This function is called when an arbiter's target socket receives a transaction from a device @@ -87,12 +87,6 @@ private: void peqCallback(tlm::tlm_generic_payload &payload, const tlm::tlm_phase &phase); - void sendToChannel(unsigned int channelId, tlm::tlm_generic_payload &payload, - const tlm::tlm_phase &phase, const sc_time &delay); - - void sendToInitiator(unsigned int id, tlm::tlm_generic_payload &payload, - const tlm::tlm_phase &phase, const sc_time &delay); - void appendDramExtension(int socketId, tlm::tlm_generic_payload &payload); std::vector nextPayloadID; };