Created cpp file for arbiter. Removed redundant routing table in arbiter.
This commit is contained in:
@@ -143,7 +143,8 @@ SOURCES += \
|
||||
src/controller/RecordableController.cpp \
|
||||
src/common/AddressDecoder.cpp \
|
||||
src/controller/scheduler/grp.cpp \
|
||||
src/common/congenAddressDecoder.cpp
|
||||
src/common/congenAddressDecoder.cpp \
|
||||
src/simulation/Arbiter.cpp
|
||||
|
||||
HEADERS += \
|
||||
src/common/third_party/tinyxml2/tinyxml2.h \
|
||||
|
||||
250
DRAMSys/library/src/simulation/Arbiter.cpp
Normal file
250
DRAMSys/library/src/simulation/Arbiter.cpp
Normal file
@@ -0,0 +1,250 @@
|
||||
/*
|
||||
* Copyright (c) 2015, University of Kaiserslautern
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions are
|
||||
* met:
|
||||
*
|
||||
* 1. Redistributions of source code must retain the above copyright notice,
|
||||
* this list of conditions and the following disclaimer.
|
||||
*
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
*
|
||||
* 3. Neither the name of the copyright holder nor the names of its
|
||||
* contributors may be used to endorse or promote products derived from
|
||||
* this software without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
|
||||
* TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
|
||||
* PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER
|
||||
* OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
|
||||
* EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
|
||||
* PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
|
||||
* PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
|
||||
* LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
|
||||
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
||||
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*
|
||||
* Authors:
|
||||
* Robert Gernhardt
|
||||
* Matthias Jung
|
||||
* Eder F. Zulian
|
||||
*/
|
||||
|
||||
#include "Arbiter.h"
|
||||
|
||||
using namespace std;
|
||||
using namespace tlm;
|
||||
|
||||
Arbiter::Arbiter(sc_module_name) : payloadEventQueue(this, &Arbiter::peqCallback)
|
||||
{
|
||||
// The arbiter communicates with one or more memory unity through one or more sockets (one or more memory channels).
|
||||
// Each of the arbiter's initiator sockets is bound to a memory controller's target socket.
|
||||
// Anytime an transaction comes from a memory unity to the arbiter the "bw" callback is called.
|
||||
iSocket.register_nb_transport_bw(this, &Arbiter::nb_transport_bw);
|
||||
|
||||
for (size_t i = 0; i < Configuration::getInstance().NumberOfMemChannels; ++i)
|
||||
{
|
||||
channelIsFree.push_back(true);
|
||||
pendingRequests.push_back(queue<tlm_generic_payload *>());
|
||||
}
|
||||
|
||||
// One or more devices can accesss all the memory units through the arbiter.
|
||||
// Devices' initiator sockets are bound to arbiter's target sockets.
|
||||
// As soon the arbiter receives a request in any of its target sockets it should treat and forward it to the proper memory channel.
|
||||
tSocket.register_nb_transport_fw(this, &Arbiter::nb_transport_fw);
|
||||
|
||||
tSocket.register_transport_dbg(this, &Arbiter::transport_dbg);
|
||||
}
|
||||
|
||||
// Initiated by initiator side
|
||||
// This function is called when an arbiter's target socket receives a transaction from a device
|
||||
tlm_sync_enum Arbiter::nb_transport_fw(int id, tlm_generic_payload &payload,
|
||||
tlm_phase &phase, sc_time &fwDelay)
|
||||
{
|
||||
sc_time notDelay = clkAlign(sc_time_stamp() + fwDelay) -
|
||||
(sc_time_stamp() + fwDelay);
|
||||
if (phase == BEGIN_REQ)
|
||||
{
|
||||
// adjust address offset:
|
||||
payload.set_address(payload.get_address() -
|
||||
Configuration::getInstance().AddressOffset);
|
||||
|
||||
// In the begin request phase the socket ID is appended to the payload.
|
||||
// It will extracted from the payload and used later.
|
||||
appendDramExtension(id, payload);
|
||||
payload.acquire();
|
||||
}
|
||||
else if (phase == END_RESP)
|
||||
{
|
||||
notDelay += Configuration::getInstance().memSpec.clk;
|
||||
payload.release();
|
||||
}
|
||||
|
||||
printDebugMessage("[fw] " + phaseNameToString(phase) + " notification in " +
|
||||
notDelay.to_string());
|
||||
payloadEventQueue.notify(payload, phase, notDelay);
|
||||
return TLM_ACCEPTED;
|
||||
}
|
||||
|
||||
// Initiated by dram side
|
||||
// This function is called when an arbiter's initiator socket receives a transaction from a memory controller
|
||||
tlm_sync_enum Arbiter::nb_transport_bw(int channelId, tlm_generic_payload &payload,
|
||||
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");
|
||||
|
||||
printDebugMessage("[bw] " + phaseNameToString(phase) + " notification in " +
|
||||
bwDelay.to_string());
|
||||
payloadEventQueue.notify(payload, phase, bwDelay);
|
||||
return TLM_ACCEPTED;
|
||||
}
|
||||
|
||||
unsigned int Arbiter::transport_dbg(int /*id*/, tlm::tlm_generic_payload &trans)
|
||||
{
|
||||
// adjust address offset:
|
||||
trans.set_address(trans.get_address() -
|
||||
Configuration::getInstance().AddressOffset);
|
||||
|
||||
DecodedAddress decodedAddress = AddressDecoder::getInstance().decodeAddress(
|
||||
trans.get_address());
|
||||
return iSocket[decodedAddress.channel]->transport_dbg(trans);
|
||||
}
|
||||
|
||||
void Arbiter::peqCallback(tlm_generic_payload &payload, const tlm_phase &phase)
|
||||
{
|
||||
unsigned int initiatorSocket = DramExtension::getExtension(
|
||||
payload).getThread().ID();
|
||||
unsigned int channelId = DramExtension::getExtension(payload).getChannel().ID();
|
||||
|
||||
// Check the valid range of initiatorSocket ID and channel Id
|
||||
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]) {
|
||||
// This channel was available. Forward the new transaction to the memory controller.
|
||||
channelIsFree[channelId] = false;
|
||||
sendToChannel(channelId, payload, phase, SC_ZERO_TIME);
|
||||
} 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) {
|
||||
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);
|
||||
|
||||
// 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();
|
||||
// Send ONE of the enqueued new transactions (phase is BEGIN_REQ) through this channel.
|
||||
sendToChannel(channelId, *payloadToSend, BEGIN_REQ, SC_ZERO_TIME);
|
||||
// Mark the channel as busy again.
|
||||
channelIsFree[channelId] = false;
|
||||
}
|
||||
}
|
||||
else if (phase == BEGIN_RESP)
|
||||
{
|
||||
// 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);
|
||||
}
|
||||
// Enqueue the transaction in BEGIN_RESP phase until the initiator
|
||||
// device acknowledge it (phase changes to END_RESP).
|
||||
receivedResponses[initiatorSocket].push(&payload);
|
||||
}
|
||||
else if (phase == END_RESP)
|
||||
{
|
||||
// Send the END_RESP message to the memory
|
||||
sendToChannel(channelId, payload, phase, SC_ZERO_TIME);
|
||||
// Drop one element of the queue of BEGIN_RESP from memory to this device
|
||||
receivedResponses[initiatorSocket].pop();
|
||||
|
||||
// Check if there are queued transactoins with phase BEGIN_RESP from memory to this device
|
||||
if (!receivedResponses[initiatorSocket].empty()) {
|
||||
// The queue is not empty.
|
||||
tlm_generic_payload *payloadToSend = receivedResponses[initiatorSocket].front();
|
||||
// Send ONE extra BEGIN_RESP to the device
|
||||
sendToInitiator(initiatorSocket, *payloadToSend, BEGIN_RESP, SC_ZERO_TIME);
|
||||
}
|
||||
}
|
||||
else
|
||||
SC_REPORT_FATAL(0,
|
||||
"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
|
||||
GenerationExtension *genExtension = new GenerationExtension(sc_time_stamp());
|
||||
payload.set_auto_extension(genExtension);
|
||||
|
||||
unsigned int burstlength = payload.get_streaming_width();
|
||||
DecodedAddress decodedAddress = AddressDecoder::getInstance().decodeAddress(payload.get_address());
|
||||
// Check the valid range of decodedAddress
|
||||
if (addressIsValid(decodedAddress)) {
|
||||
DramExtension *extension = new DramExtension(Thread(socketId),
|
||||
Channel(decodedAddress.channel), Bank(decodedAddress.bank),
|
||||
BankGroup(decodedAddress.bankgroup), Row(decodedAddress.row),
|
||||
Column(decodedAddress.column), burstlength);
|
||||
payload.set_auto_extension(extension);
|
||||
} else {
|
||||
SC_REPORT_FATAL("Arbiter", "Decoded Address is not inside the valid range");
|
||||
}
|
||||
}
|
||||
|
||||
bool Arbiter::addressIsValid(DecodedAddress &decodedAddress)
|
||||
{
|
||||
if (decodedAddress.channel >= AddressDecoder::getInstance().amount["channel"]) {
|
||||
return false;
|
||||
}
|
||||
if (decodedAddress.bank >= AddressDecoder::getInstance().amount["bank"]) {
|
||||
return false;
|
||||
}
|
||||
if (decodedAddress.bankgroup >
|
||||
AddressDecoder::getInstance().amount["bankgroup"]) {
|
||||
return false;
|
||||
}
|
||||
if (decodedAddress.column >= AddressDecoder::getInstance().amount["column"]) {
|
||||
return false;
|
||||
}
|
||||
if (decodedAddress.row >= AddressDecoder::getInstance().amount["row"]) {
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
void Arbiter::printDebugMessage(std::string message)
|
||||
{
|
||||
DebugManager::getInstance().printDebugMessage(this->name(), message);
|
||||
}
|
||||
@@ -54,31 +54,14 @@
|
||||
using namespace std;
|
||||
using namespace tlm;
|
||||
|
||||
struct Arbiter : public sc_module {
|
||||
class Arbiter : public sc_module
|
||||
{
|
||||
public:
|
||||
tlm_utils::multi_passthrough_initiator_socket<Arbiter> iSocket;
|
||||
tlm_utils::multi_passthrough_target_socket<Arbiter> tSocket;
|
||||
|
||||
SC_CTOR(Arbiter) : payloadEventQueue(this, &Arbiter::peqCallback)
|
||||
{
|
||||
// The arbiter communicates with one or more memory unity through one or more sockets (one or more memory channels).
|
||||
// Each of the arbiter's initiator sockets is bound to a memory controller's target socket.
|
||||
// Anytime an transaction comes from a memory unity to the arbiter the "bw" callback is called.
|
||||
iSocket.register_nb_transport_bw(this, &Arbiter::nb_transport_bw);
|
||||
|
||||
for (size_t i = 0; i < Configuration::getInstance().NumberOfMemChannels; ++i)
|
||||
{
|
||||
channelIsFree.push_back(true);
|
||||
pendingRequests.push_back(queue<tlm_generic_payload *>());
|
||||
}
|
||||
|
||||
// One or more devices can accesss all the memory units through the arbiter.
|
||||
// Devices' initiator sockets are bound to arbiter's target sockets.
|
||||
// As soon the arbiter receives a request in any of its target sockets it should treat and forward it to the proper memory channel.
|
||||
tSocket.register_nb_transport_fw(this, &Arbiter::nb_transport_fw);
|
||||
|
||||
tSocket.register_transport_dbg(this, &Arbiter::transport_dbg);
|
||||
}
|
||||
Arbiter(sc_module_name);
|
||||
SC_HAS_PROCESS(Arbiter);
|
||||
|
||||
private:
|
||||
tlm_utils::peq_with_cb_and_phase<Arbiter> payloadEventQueue;
|
||||
@@ -92,210 +75,31 @@ private:
|
||||
// This is a queue of responses comming from the memory side. The phase of these transactions is BEGIN_RESP.
|
||||
std::map<unsigned int, queue<tlm_generic_payload *>> receivedResponses;
|
||||
|
||||
// used to map the transaction from devices to the arbiter's target socket ID.
|
||||
std::map<tlm_generic_payload *, int> routeMap;
|
||||
|
||||
|
||||
// Initiated by initiator side
|
||||
// This function is called when an arbiter's target socket receives a transaction from a device
|
||||
tlm_sync_enum nb_transport_fw(int id, tlm_generic_payload &payload,
|
||||
tlm_phase &phase, sc_time &fwDelay)
|
||||
{
|
||||
sc_time notDelay = clkAlign(sc_time_stamp() + fwDelay) -
|
||||
(sc_time_stamp() + fwDelay);
|
||||
if (phase == BEGIN_REQ)
|
||||
{
|
||||
// adjust address offset:
|
||||
payload.set_address(payload.get_address() -
|
||||
Configuration::getInstance().AddressOffset);
|
||||
|
||||
// Map the payload with socket id.
|
||||
routeMap[&payload] = id;
|
||||
|
||||
// In the begin request phase the socket ID is appended to the payload.
|
||||
// It will extracted from the payload and used later.
|
||||
appendDramExtension(id, payload);
|
||||
payload.acquire();
|
||||
}
|
||||
else if (phase == END_RESP)
|
||||
{
|
||||
notDelay += Configuration::getInstance().memSpec.clk;
|
||||
// Erase before the payload is released.
|
||||
routeMap.erase(&payload);
|
||||
payload.release();
|
||||
}
|
||||
|
||||
printDebugMessage("[fw] " + phaseNameToString(phase) + " notification in " +
|
||||
notDelay.to_string());
|
||||
payloadEventQueue.notify(payload, phase, notDelay);
|
||||
return TLM_ACCEPTED;
|
||||
}
|
||||
tlm_phase &phase, sc_time &fwDelay);
|
||||
|
||||
// Initiated by dram side
|
||||
// This function is called when an arbiter's initiator socket receives a transaction from a memory controller
|
||||
tlm_sync_enum nb_transport_bw(int channelId, tlm_generic_payload &payload,
|
||||
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");
|
||||
tlm_phase &phase, sc_time &bwDelay);
|
||||
|
||||
printDebugMessage("[bw] " + phaseNameToString(phase) + " notification in " +
|
||||
bwDelay.to_string());
|
||||
payloadEventQueue.notify(payload, phase, bwDelay);
|
||||
return TLM_ACCEPTED;
|
||||
}
|
||||
virtual unsigned int transport_dbg(int /*id*/, tlm::tlm_generic_payload &trans);
|
||||
|
||||
virtual unsigned int transport_dbg(int /*id*/, tlm::tlm_generic_payload &trans)
|
||||
{
|
||||
// adjust address offset:
|
||||
trans.set_address(trans.get_address() -
|
||||
Configuration::getInstance().AddressOffset);
|
||||
|
||||
DecodedAddress decodedAddress = AddressDecoder::getInstance().decodeAddress(
|
||||
trans.get_address());
|
||||
return iSocket[decodedAddress.channel]->transport_dbg(trans);
|
||||
}
|
||||
|
||||
void peqCallback(tlm_generic_payload &payload, const tlm_phase &phase)
|
||||
{
|
||||
unsigned int initiatorSocket = DramExtension::getExtension(
|
||||
payload).getThread().ID();
|
||||
unsigned int channelId = DramExtension::getExtension(payload).getChannel().ID();
|
||||
|
||||
// Check the valid range of initiatorSocket ID and channel Id
|
||||
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]) {
|
||||
// This channel was available. Forward the new transaction to the memory controller.
|
||||
channelIsFree[channelId] = false;
|
||||
sendToChannel(channelId, payload, phase, SC_ZERO_TIME);
|
||||
} 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) {
|
||||
channelIsFree[channelId] = true;
|
||||
// Validate the initiatorSocket ID
|
||||
if ((int)initiatorSocket != routeMap[&payload]) {
|
||||
SC_REPORT_FATAL("Arbiter", "Payload extension was corrupted");
|
||||
}
|
||||
// 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);
|
||||
|
||||
// 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();
|
||||
// Send ONE of the enqueued new transactions (phase is BEGIN_REQ) through this channel.
|
||||
sendToChannel(channelId, *payloadToSend, BEGIN_REQ, SC_ZERO_TIME);
|
||||
// Mark the channel as busy again.
|
||||
channelIsFree[channelId] = false;
|
||||
}
|
||||
}
|
||||
else if (phase == BEGIN_RESP)
|
||||
{
|
||||
// Validate the initiatorSocket ID
|
||||
if ((int)initiatorSocket != routeMap[&payload]) {
|
||||
SC_REPORT_FATAL("Arbiter", "Payload extension was corrupted");
|
||||
}
|
||||
// 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);
|
||||
}
|
||||
// Enqueue the transaction in BEGIN_RESP phase until the initiator
|
||||
// device acknowledge it (phase changes to END_RESP).
|
||||
receivedResponses[initiatorSocket].push(&payload);
|
||||
}
|
||||
else if (phase == END_RESP)
|
||||
{
|
||||
// Send the END_RESP message to the memory
|
||||
sendToChannel(channelId, payload, phase, SC_ZERO_TIME);
|
||||
// Drop one element of the queue of BEGIN_RESP from memory to this device
|
||||
receivedResponses[initiatorSocket].pop();
|
||||
|
||||
// Check if there are queued transactoins with phase BEGIN_RESP from memory to this device
|
||||
if (!receivedResponses[initiatorSocket].empty()) {
|
||||
// The queue is not empty.
|
||||
tlm_generic_payload *payloadToSend = receivedResponses[initiatorSocket].front();
|
||||
// Send ONE extra BEGIN_RESP to the device
|
||||
sendToInitiator(initiatorSocket, *payloadToSend, BEGIN_RESP, SC_ZERO_TIME);
|
||||
}
|
||||
}
|
||||
else
|
||||
SC_REPORT_FATAL(0,
|
||||
"Payload event queue in arbiter was triggered with unknown phase");
|
||||
}
|
||||
void peqCallback(tlm_generic_payload &payload, const tlm_phase &phase);
|
||||
|
||||
void 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);
|
||||
}
|
||||
const tlm_phase &phase, const sc_time &delay);
|
||||
|
||||
void 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);
|
||||
}
|
||||
const tlm_phase &phase, const sc_time &delay);
|
||||
|
||||
void appendDramExtension(int socketId, tlm_generic_payload &payload)
|
||||
{
|
||||
// Append Generation Extension
|
||||
GenerationExtension *genExtension = new GenerationExtension(sc_time_stamp());
|
||||
payload.set_auto_extension(genExtension);
|
||||
void appendDramExtension(int socketId, tlm_generic_payload &payload);
|
||||
|
||||
unsigned int burstlength = payload.get_streaming_width();
|
||||
DecodedAddress decodedAddress = AddressDecoder::getInstance().decodeAddress(
|
||||
payload.get_address());
|
||||
// Check the valid range of decodedAddress
|
||||
if (addressIsValid(decodedAddress)) {
|
||||
DramExtension *extension = new DramExtension(Thread(socketId),
|
||||
Channel(decodedAddress.channel), Bank(decodedAddress.bank),
|
||||
BankGroup(decodedAddress.bankgroup), Row(decodedAddress.row),
|
||||
Column(decodedAddress.column), burstlength);
|
||||
payload.set_auto_extension(extension);
|
||||
} else {
|
||||
SC_REPORT_FATAL("Arbiter", "Decoded Address are not inside the valid range");
|
||||
}
|
||||
}
|
||||
bool addressIsValid(DecodedAddress &decodedAddress);
|
||||
|
||||
bool addressIsValid(DecodedAddress &decodedAddress)
|
||||
{
|
||||
if (decodedAddress.channel >= AddressDecoder::getInstance().amount["channel"]) {
|
||||
return false;
|
||||
}
|
||||
if (decodedAddress.bank >= AddressDecoder::getInstance().amount["bank"]) {
|
||||
return false;
|
||||
}
|
||||
if (decodedAddress.bankgroup >
|
||||
AddressDecoder::getInstance().amount["bankgroup"]) {
|
||||
return false;
|
||||
}
|
||||
if (decodedAddress.column >= AddressDecoder::getInstance().amount["column"]) {
|
||||
return false;
|
||||
}
|
||||
if (decodedAddress.row >= AddressDecoder::getInstance().amount["row"]) {
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
void printDebugMessage(std::string message)
|
||||
{
|
||||
DebugManager::getInstance().printDebugMessage(this->name(), message);
|
||||
}
|
||||
void printDebugMessage(std::string message);
|
||||
};
|
||||
|
||||
#endif /* ARBITER_H_ */
|
||||
|
||||
@@ -86,7 +86,6 @@ public:
|
||||
} else {
|
||||
numberOfTransactions++;
|
||||
}
|
||||
|
||||
// Allocate a generic payload for this request.
|
||||
gp *payload = this->allocatePayload();
|
||||
|
||||
@@ -170,16 +169,17 @@ public:
|
||||
payload->set_data_ptr(data);
|
||||
payload->set_command(cmd);
|
||||
|
||||
if (relative == false) {
|
||||
if (relative == false)
|
||||
{
|
||||
// Send the transaction directly or schedule it to be sent in the future.
|
||||
if (sendingTime <= sc_time_stamp())
|
||||
this->payloadEventQueue.notify(*payload, BEGIN_REQ, SC_ZERO_TIME);
|
||||
else
|
||||
this->payloadEventQueue.notify(*payload, BEGIN_REQ,
|
||||
sendingTime - sc_time_stamp());
|
||||
} else {
|
||||
payloadEventQueue.notify(*payload, BEGIN_REQ, sendingTime);
|
||||
}
|
||||
else
|
||||
payloadEventQueue.notify(*payload, BEGIN_REQ, sendingTime);
|
||||
}
|
||||
|
||||
private:
|
||||
@@ -188,7 +188,7 @@ private:
|
||||
|
||||
unsigned int burstlength;
|
||||
unsigned int dataLength;
|
||||
sc_time playerClk; // May be different from from the memory clock!
|
||||
sc_time playerClk; // May be different from the memory clock!
|
||||
};
|
||||
|
||||
#endif // STLPLAYER_H
|
||||
|
||||
@@ -80,7 +80,6 @@ tlm_sync_enum TracePlayer::nb_transport_bw(tlm_generic_payload &payload,
|
||||
void TracePlayer::peqCallback(tlm_generic_payload &payload,
|
||||
const tlm_phase &phase)
|
||||
{
|
||||
|
||||
if (phase == BEGIN_REQ) {
|
||||
payload.acquire();
|
||||
sendToTarget(payload, phase, SC_ZERO_TIME);
|
||||
@@ -99,7 +98,8 @@ void TracePlayer::peqCallback(tlm_generic_payload &payload,
|
||||
transactionsReceived++;
|
||||
|
||||
// If all answers were received:
|
||||
if (finished == true && numberOfTransactions == transactionsReceived) {
|
||||
if (finished == true && numberOfTransactions == transactionsReceived)
|
||||
{
|
||||
this->terminate();
|
||||
}
|
||||
} else if (phase == END_RESP) {
|
||||
@@ -108,6 +108,13 @@ void TracePlayer::peqCallback(tlm_generic_payload &payload,
|
||||
}
|
||||
}
|
||||
|
||||
void TracePlayer::sendToTarget(tlm_generic_payload &payload, const tlm_phase &phase, const sc_time &delay)
|
||||
{
|
||||
tlm_phase TPhase = phase;
|
||||
sc_time TDelay = delay;
|
||||
iSocket->nb_transport_fw(payload, TPhase, TDelay);
|
||||
}
|
||||
|
||||
void TracePlayer::setNumberOfTransactions(unsigned int n)
|
||||
{
|
||||
numberOfTransactions = n;
|
||||
|
||||
@@ -77,12 +77,7 @@ private:
|
||||
sc_time &bwDelay);
|
||||
void peqCallback(tlm_generic_payload &payload, const tlm_phase &phase);
|
||||
void sendToTarget(tlm_generic_payload &payload, const tlm_phase &phase,
|
||||
const sc_time &delay)
|
||||
{
|
||||
tlm_phase TPhase = phase;
|
||||
sc_time TDelay = delay;
|
||||
iSocket->nb_transport_fw(payload, TPhase, TDelay);
|
||||
}
|
||||
const sc_time &delay);
|
||||
MemoryManager memoryManager;
|
||||
unsigned int transactionsSent;
|
||||
unsigned int transactionsReceived;
|
||||
|
||||
@@ -56,9 +56,10 @@ traceSetup::traceSetup(std::string uri,
|
||||
simulation->FirstChildElement("tracesetup");
|
||||
|
||||
for (tinyxml2::XMLElement *device =
|
||||
tracesetup->FirstChildElement("device");
|
||||
device != NULL;
|
||||
device = device->NextSiblingElement("device")) {
|
||||
tracesetup->FirstChildElement("device");
|
||||
device != NULL;
|
||||
device = device->NextSiblingElement("device"))
|
||||
{
|
||||
sc_time playerClk;
|
||||
unsigned int frequency = device->IntAttribute("clkMhz");
|
||||
|
||||
@@ -83,12 +84,12 @@ traceSetup::traceSetup(std::string uri,
|
||||
std::string moduleName = name;
|
||||
|
||||
// replace all '.' to '_'
|
||||
std::replace( moduleName.begin(), moduleName.end(), '.', '_');
|
||||
std::replace(moduleName.begin(), moduleName.end(), '.', '_');
|
||||
|
||||
TracePlayer *player;
|
||||
if (strcmp(ext.c_str(), "stl") == 0) {
|
||||
if (ext == "stl") {
|
||||
player = new StlPlayer<false>(moduleName.c_str(), stlFile, playerClk, this);
|
||||
} else if (strcmp(ext.c_str(), "rstl") == 0) {
|
||||
} else if (ext == "rstl") {
|
||||
player = new StlPlayer<true>(moduleName.c_str(), stlFile, playerClk, this);
|
||||
} else {
|
||||
std::string error = "Unsupported file extension in " + name;
|
||||
|
||||
Reference in New Issue
Block a user