Make controller easier to understand.

This commit is contained in:
Lukas Steiner
2020-10-20 09:32:28 +02:00
parent 0501bbd2c8
commit 328a371843
3 changed files with 72 additions and 62 deletions

View File

@@ -219,24 +219,14 @@ Controller::~Controller()
void Controller::controllerMethod()
{
// clear command buffer
readyCommands.clear();
// (1) Release payload if arbiter has accepted the result (finish END_RESP)
if (payloadToRelease != nullptr && timeToRelease <= sc_time_stamp())
finishEndResp();
finishEndResp();
// (2) Send next result to arbiter (start BEGIN_RESP)
if (payloadToRelease == nullptr)
startBeginResp();
startBeginResp();
// (3) Insert new request from arbiter into scheduler and restart appropriate BM (finish BEGIN_REQ)
if (payloadToAcquire != nullptr && timeToAcquire <= sc_time_stamp())
{
unsigned bankID = DramExtension::getBank(payloadToAcquire).ID();
finishBeginReq();
bankMachines[bankID]->start();
}
finishBeginReq();
// (4) Start refresh and power-down managers to issue requests for the current time
for (auto it : refreshManagers)
@@ -244,8 +234,10 @@ void Controller::controllerMethod()
for (auto it : powerDownManagers)
it->start();
// (5) Choose one request and send it to DRAM
// (5) Collect all ready commands from BMs, RMs and PDMs
CommandTuple::Type commandTuple;
// clear command buffer
readyCommands.clear();
for (unsigned rankID = 0; rankID < memSpec->numberOfRanks; rankID++)
{
@@ -270,6 +262,7 @@ void Controller::controllerMethod()
}
}
// (6) Select one of the ready commands and issue it to the DRAM
bool readyCmdBlocked = false;
if (!readyCommands.empty())
{
@@ -314,12 +307,10 @@ void Controller::controllerMethod()
readyCmdBlocked = true;
}
// (6) Accept request from arbiter if scheduler is not full, otherwise backpressure (start END_REQ)
if (payloadToAcquire != nullptr && timeToAcquire == sc_max_time())
startEndReq();
// (7) Accept request from arbiter if scheduler is not full, otherwise backpressure (start END_REQ)
startEndReq();
// (7) Restart bank machines, refresh managers and power-down managers to issue new requests for the future
// TODO: check if all calls are necessary
// (8) Restart bank machines, refresh managers and power-down managers to issue new requests for the future
sc_time timeForNextTrigger = sc_max_time();
for (auto it : bankMachines)
{
@@ -343,13 +334,13 @@ tlm_sync_enum Controller::nb_transport_fw(tlm_generic_payload &trans,
if (phase == BEGIN_REQ)
{
payloadToAcquire = &trans;
timeToAcquire = sc_time_stamp() + notificationDelay;
transToAcquire.payload = &trans;
transToAcquire.time = sc_time_stamp() + notificationDelay;
beginReqEvent.notify(notificationDelay);
}
else if (phase == END_RESP)
{
timeToRelease = sc_time_stamp() + notificationDelay;
transToRelease.time = sc_time_stamp() + notificationDelay;
endRespEvent.notify(notificationDelay);
}
else
@@ -375,63 +366,80 @@ unsigned int Controller::transport_dbg(tlm_generic_payload &trans)
void Controller::finishBeginReq()
{
NDEBUG_UNUSED(uint64_t id) = DramExtension::getPayloadID(payloadToAcquire);
PRINTDEBUGMESSAGE(name(), "Payload " + std::to_string(id) + " entered system.");
if (transToAcquire.payload != nullptr && transToAcquire.time <= sc_time_stamp())
{
NDEBUG_UNUSED(uint64_t id) = DramExtension::getPayloadID(transToAcquire.payload);
PRINTDEBUGMESSAGE(name(), "Payload " + std::to_string(id) + " entered system.");
if (totalNumberOfPayloads == 0)
idleTimeCollector.end();
totalNumberOfPayloads++;
if (totalNumberOfPayloads == 0)
idleTimeCollector.end();
totalNumberOfPayloads++;
Rank rank = DramExtension::getRank(payloadToAcquire);
if (ranksNumberOfPayloads[rank.ID()] == 0)
powerDownManagers[rank.ID()]->triggerExit();
Rank rank = DramExtension::getRank(transToAcquire.payload);
if (ranksNumberOfPayloads[rank.ID()] == 0)
powerDownManagers[rank.ID()]->triggerExit();
ranksNumberOfPayloads[rank.ID()]++;
ranksNumberOfPayloads[rank.ID()]++;
scheduler->storeRequest(payloadToAcquire);
payloadToAcquire->acquire();
timeToAcquire = sc_max_time();
scheduler->storeRequest(transToAcquire.payload);
transToAcquire.payload->acquire();
transToAcquire.time = sc_max_time();
Bank bank = DramExtension::getBank(transToAcquire.payload);
bankMachines[bank.ID()]->start();
}
}
void Controller::startEndReq()
{
if (scheduler->hasBufferSpace())
if (transToAcquire.payload != nullptr && transToAcquire.time == sc_max_time())
{
payloadToAcquire->set_response_status(TLM_OK_RESPONSE);
sendToFrontend(payloadToAcquire, END_REQ);
payloadToAcquire = nullptr;
if (scheduler->hasBufferSpace())
{
transToAcquire.payload->set_response_status(TLM_OK_RESPONSE);
sendToFrontend(transToAcquire.payload, END_REQ);
transToAcquire.payload = nullptr;
}
else
PRINTDEBUGMESSAGE(name(), "Total number of payloads exceeded, backpressure!");
}
else
PRINTDEBUGMESSAGE(name(), "Total number of payloads exceeded, backpressure!");
}
void Controller::startBeginResp()
{
payloadToRelease = respQueue->nextPayload();
if (payloadToRelease != nullptr)
sendToFrontend(payloadToRelease, BEGIN_RESP);
else
if (transToRelease.payload == nullptr)
{
sc_time triggerTime = respQueue->getTriggerTime();
if (triggerTime != sc_max_time())
dataResponseEvent.notify(triggerTime - sc_time_stamp());
transToRelease.payload = respQueue->nextPayload();
if (transToRelease.payload != nullptr)
{
transToRelease.time = sc_max_time();
sendToFrontend(transToRelease.payload, BEGIN_RESP);
}
else
{
sc_time triggerTime = respQueue->getTriggerTime();
if (triggerTime != sc_max_time())
dataResponseEvent.notify(triggerTime - sc_time_stamp());
}
}
}
void Controller::finishEndResp()
{
NDEBUG_UNUSED(uint64_t id) = DramExtension::getPayloadID(payloadToRelease);
PRINTDEBUGMESSAGE(name(), "Payload " + std::to_string(id) + " left system.");
if (transToRelease.payload != nullptr && transToRelease.time <= sc_time_stamp())
{
NDEBUG_UNUSED(uint64_t id) = DramExtension::getPayloadID(transToRelease.payload);
PRINTDEBUGMESSAGE(name(), "Payload " + std::to_string(id) + " left system.");
payloadToRelease->release();
payloadToRelease = nullptr;
timeToRelease = sc_max_time();
numberOfTransactionsServed++;
transToRelease.payload->release();
transToRelease.payload = nullptr;
numberOfTransactionsServed++;
totalNumberOfPayloads--;
if (totalNumberOfPayloads == 0)
idleTimeCollector.start();
totalNumberOfPayloads--;
if (totalNumberOfPayloads == 0)
idleTimeCollector.start();
}
}
void Controller::sendToFrontend(tlm_generic_payload *payload, tlm_phase phase)

View File

@@ -88,10 +88,11 @@ private:
std::vector<RefreshManagerIF *> refreshManagers;
std::vector<PowerDownManagerIF *> powerDownManagers;
tlm::tlm_generic_payload *payloadToAcquire = nullptr;
sc_time timeToAcquire = sc_max_time();
tlm::tlm_generic_payload *payloadToRelease = nullptr;
sc_time timeToRelease = sc_max_time();
struct Transaction
{
tlm::tlm_generic_payload *payload = nullptr;
sc_time time = sc_max_time();
} transToAcquire, transToRelease;
void finishBeginReq();
void startEndReq();

View File

@@ -43,6 +43,7 @@
#include <iostream>
#include <vector>
#include <queue>
#include <unordered_map>
#include <tlm_utils/multi_passthrough_target_socket.h>
#include <tlm_utils/multi_passthrough_initiator_socket.h>
#include <tlm_utils/peq_with_cb_and_phase.h>
@@ -70,7 +71,7 @@ private:
std::vector<std::queue<tlm::tlm_generic_payload *>> 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<unsigned int, std::queue<tlm::tlm_generic_payload *>> pendingResponses;
std::unordered_map<unsigned int, std::queue<tlm::tlm_generic_payload *>> pendingResponses;
// Initiated by initiator side
// This function is called when an arbiter's target socket receives a transaction from a device