Removed arbiter's send methods to implement early completion.
This commit is contained in:
@@ -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);
|
||||
}
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -71,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 *>> receivedResponses;
|
||||
std::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
|
||||
@@ -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<uint64_t> nextPayloadID;
|
||||
};
|
||||
|
||||
Reference in New Issue
Block a user