diff --git a/dram/resources/simulations/sim-batch.xml b/dram/resources/simulations/sim-batch.xml
index 43e20eed..0362bd10 100644
--- a/dram/resources/simulations/sim-batch.xml
+++ b/dram/resources/simulations/sim-batch.xml
@@ -3,6 +3,8 @@
+
+
@@ -11,12 +13,12 @@
-
+
- chstone-adpcm_32.stl
+ voco2.stl
diff --git a/dram/src/controller/core/configuration/Configuration.cpp b/dram/src/controller/core/configuration/Configuration.cpp
index 8b1d926f..aa321acd 100644
--- a/dram/src/controller/core/configuration/Configuration.cpp
+++ b/dram/src/controller/core/configuration/Configuration.cpp
@@ -32,6 +32,7 @@
* Authors:
* Janik Schlemminger
* Matthias Jung
+ * Eder F. Zulian
*/
#include "Configuration.h"
@@ -123,6 +124,10 @@ void Configuration::setParameter(std::string name, std::string value)
ErrorCSVFile = value;
else if(name == "ErrorStoreMode")
ErrorStoreMode = StringToEnum(value);
+ else if (name == "NumberOfTracePlayers")
+ NumberOfTracePlayers = string2int(value);
+ else if (name == "NumberOfMemChannels")
+ NumberOfMemChannels = string2int(value);
else
{
SC_REPORT_FATAL("Configuration", ("Parameter " + name + " not defined in Configuration").c_str());
diff --git a/dram/src/controller/core/configuration/Configuration.h b/dram/src/controller/core/configuration/Configuration.h
index 7cdab17c..37108792 100644
--- a/dram/src/controller/core/configuration/Configuration.h
+++ b/dram/src/controller/core/configuration/Configuration.h
@@ -32,6 +32,7 @@
* Authors:
* Janik Schlemminger
* Matthias Jung
+ * Eder F. Zulian
*/
#ifndef CONFIGURATION_H_
@@ -72,6 +73,8 @@ struct Configuration
bool DatabaseRecording = true;
bool PowerAnalysis = false;
bool Debug = false;
+ unsigned int NumberOfTracePlayers = 4;
+ unsigned int NumberOfMemChannels = 1;
//MemSpec(from DRAM-Power XML)
MemSpec memSpec;
diff --git a/dram/src/simulation/Arbiter.h b/dram/src/simulation/Arbiter.h
index 69215235..2c8d096a 100644
--- a/dram/src/simulation/Arbiter.h
+++ b/dram/src/simulation/Arbiter.h
@@ -38,70 +38,81 @@
#ifndef ARBITER_H_
#define ARBITER_H_
-#include
#include
#include
#include
-#include
-#include
+#include
+#include
+#include
+#include
#include
#include "../common/xmlAddressdecoder.h"
#include "../common/dramExtension.h"
#include "../controller/core/TimingCalculation.h"
+#include "../controller/core/configuration/ConfigurationLoader.h"
using namespace std;
using namespace tlm;
-template<
- unsigned int NUMBER_OF_THREADS = 1,
- unsigned int BUSWIDTH = 128,
- unsigned int NUMBER_OF_CHANNELS = 1
->
+template
struct Arbiter: public sc_module {
public:
- tlm_utils::simple_initiator_socket_tagged iSocket[NUMBER_OF_CHANNELS];
- tlm_utils::simple_target_socket_tagged tSockets[NUMBER_OF_THREADS];
+ tlm_utils::multi_passthrough_initiator_socket iSocket;
+ tlm_utils::multi_passthrough_target_socket tSocket;
SC_CTOR(Arbiter) : payloadEventQueue(this, &Arbiter::peqCallback) {
- for (unsigned int i = 0; i < NUMBER_OF_CHANNELS; ++i) {
- // The arbiter communicates with one or more memory controller through one or more sockets (one or more memory channels).
- // Each of the arbiter's iniitator sockets is binded to a memory controller's target socket.
- // In this case the arbiter is the initiator.
- iSocket[i].register_nb_transport_bw(this, &Arbiter::nb_transport_bw, i);
- channelIsFree[i] = true;
+ // 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());
}
- for (unsigned int i = 0; i < NUMBER_OF_THREADS; ++i) {
- // One or more devices can accesss the memory throught the arbiter. A device can be a processor's core, the execution of a previously recorded trace file, etc.
- // As soon the arbiter receives a request in any of its target sockets it should treat and forward it to the proper memory channel.
- // In this case the arbiter acts as a target.
- tSockets[i].register_nb_transport_fw(this, &Arbiter::nb_transport_fw, i);
+
+ // 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);
+
+ for (size_t i = 0; i < Configuration::getInstance().NumberOfTracePlayers; ++i) {
+ receivedResponses.push_back(queue());
}
}
private:
tlm_utils::peq_with_cb_and_phase payloadEventQueue;
- bool channelIsFree[NUMBER_OF_CHANNELS];
+
+ vector channelIsFree;
+
//used to account for the request_accept_delay in the dram controllers
- deque pendingRequests[NUMBER_OF_CHANNELS];
+ // This is a queue of new transactions. The phase of a new request is BEGIN_REQ.
+ vector> pendingRequests;
//used to account for the response_accept_delay in the initiators (traceplayer,core etc.)
- deque receivedResponses[NUMBER_OF_THREADS];
+ // This is a queue of responses comming from the memory side. The phase of these transactions is BEGIN_RESP.
+ vector> receivedResponses;
// Initiated by dram side
- tlm_sync_enum nb_transport_bw(__attribute__((unused)) int socketId, tlm_generic_payload& payload, tlm_phase& phase, sc_time& bwDelay)
+ // This function is called when an arbiter's initiator socket receives a transaction from a memory controller
+ tlm_sync_enum nb_transport_bw(__attribute__((unused)) int id, tlm_generic_payload& payload, tlm_phase& phase, sc_time& bwDelay)
{
TlmRecorder::getInstance().recordPhase(payload, phase, bwDelay + sc_time_stamp());
payloadEventQueue.notify(payload, phase, bwDelay);
return TLM_ACCEPTED;
}
+ // TODO: check this id. How the payload extension propagates and is used...
+ // TODO: check the index mechanism for initiator and target sockets. Assert the index to be valid.
+
// Initiated by initiator side
- // Anytime the arbiter receives a message from a device this callback function is called
- tlm_sync_enum nb_transport_fw(int socketId, tlm_generic_payload& payload, tlm_phase& phase, sc_time& fwDelay)
+ // 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)
{
if (phase == BEGIN_REQ) {
// In the begin request phase the socket ID is appended to the payload.
// It will extracted from the payload and used later.
- appendDramExtension(socketId, payload);
+ appendDramExtension(id, payload);
payload.acquire();
} else if (phase == END_RESP) {
payload.release();
@@ -116,55 +127,54 @@ private:
unsigned int initiatorSocket = DramExtension::getExtension(payload).getThread().ID()-1;
unsigned int channelId = DramExtension::getExtension(payload).getChannel().ID();
+ // TODO: here check if the channel and the initiatorSocket ID are valid. If not, the payload extension was corrupted.
+
// 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 the channel is available forward the request to the memory controller
+ // This channel was available. Forward the new transaction to the memory controller.
channelIsFree[channelId] = false;
sendToChannel(channelId, payload, phase, SC_ZERO_TIME);
} else {
- // If the channel is not available put the request in a queue.
- pendingRequests[channelId].push_back(&payload);
+ // This channel is busy. Enqueue the new transaction which phase is BEGIN_REQ.
+ pendingRequests[channelId].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_front();
+ receivedResponses[initiatorSocket].pop();
- // Check if there are queued BEGIN_RESP messages from memory to this device
+ // 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();
+ tlm_generic_payload *payloadToSend = receivedResponses[initiatorSocket].front();
// Send ONE extra BEGIN_RESP to the device
sendToInitiator(initiatorSocket, *payloadToSend, BEGIN_RESP, SC_ZERO_TIME);
}
}
- // Phases initiated by the target side from arbiter's point of view (memory controllers)
+ // 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 an END_REQ from memory controller and
- // forward it to the requester device.
+ // 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 queued BEGIN_REQ, if any. Send it to the memory controller.
+ // 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_front();
- // Send ONE enqueued BEGIN_REQ to throgh this channel.
+ 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 BEGIN_RESP from memory controller and
- // forwards it to the requester device
+ // 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 BEGIN_RESP. It will be dequeued later on when the
- // initiator device sends an END_RESP
- receivedResponses[initiatorSocket].push_back(&payload);
+ // Enqueue the transaction in BEGIN_RESP phase until the initiator device acknowledge it (phase changes to END_RESP).
+ receivedResponses[initiatorSocket].push(&payload);
} else {
SC_REPORT_FATAL(0, "Payload event queue in arbiter was triggered with unknown phase");
}
@@ -181,11 +191,13 @@ private:
{
tlm_phase TPhase = phase;
sc_time TDelay = delay;
- tSockets[id]->nb_transport_bw(payload, TPhase, TDelay);
+ tSocket[id]->nb_transport_bw(payload, TPhase, TDelay);
}
void appendDramExtension(int socketId, tlm_generic_payload& payload)
{
+ // TODO: check if channel valid before appending.
+ // TODO: check if all parts of the decodedAddress are inside the valid range (devices should not perform invalid requests to the arbiter, right?).
unsigned int burstlength = payload.get_streaming_width();
DecodedAddress decodedAddress = xmlAddressDecoder::getInstance().decodeAddress(payload.get_address());
DramExtension* extension = new DramExtension(Thread(socketId+1), Channel(decodedAddress.channel), Bank(decodedAddress.bank), BankGroup(decodedAddress.bankgroup), Row(decodedAddress.row), Column(decodedAddress.column),burstlength);
diff --git a/dram/src/simulation/Simulation.cpp b/dram/src/simulation/Simulation.cpp
index 63123c04..98003184 100644
--- a/dram/src/simulation/Simulation.cpp
+++ b/dram/src/simulation/Simulation.cpp
@@ -90,7 +90,14 @@ void Simulation::setupTlmRecorder(const string &traceName, const string &pathToR
TlmRecorder::sqlScriptURI = pathToResources + string("scripts/createTraceDB.sql");
TlmRecorder::getInstance().recordMemconfig(Configuration::getInstance().memconfigUri);
TlmRecorder::getInstance().recordMemspec(Configuration::getInstance().memspecUri);
- TlmRecorder::getInstance().recordTracenames(devices[0].trace + "," + devices[1].trace + "," + devices[2].trace + "," + devices[3].trace);
+ std::string traceNames;
+ for (size_t i = 0; i < devices.size(); i++) {
+ traceNames.append(devices[i].trace);
+ if (i == devices.size() - 1)
+ continue;
+ traceNames.append(",");
+ }
+ TlmRecorder::getInstance().recordTracenames(traceNames);
}
else
{
@@ -100,15 +107,15 @@ void Simulation::setupTlmRecorder(const string &traceName, const string &pathToR
void Simulation::instantiateModules(const string &pathToResources, const std::vector& devices)
{
- for (size_t i = 0; i < NumberOfTracePlayers; i++) {
+ for (size_t i = 0; i < Configuration::getInstance().NumberOfTracePlayers; i++) {
std::string playerStr = "player" + std::to_string(i);
TracePlayer<> *player = new StlPlayer<>(playerStr.c_str(), pathToResources + string("traces/") + devices[i].trace, devices[i].clkMhz, this);
players.push_back(player);
}
- arbiter = new Arbiter("arbiter");
+ arbiter = new Arbiter<128>("arbiter");
- for (size_t i = 0; i < NumberOfMemChannels; i++) {
+ for (size_t i = 0; i < Configuration::getInstance().NumberOfMemChannels; i++) {
std::string str = "controller" + std::to_string(i);
Controller<> *controller = new Controller<>(str.c_str());
controllers.push_back(controller);
@@ -123,11 +130,11 @@ void Simulation::bindSockets()
{
size_t i = 0;
for (auto player : players) {
- player->iSocket.bind(arbiter->tSockets[i++]);
+ player->iSocket.bind(arbiter->tSocket);
}
- for (i = 0; i < NumberOfMemChannels; i++) {
- arbiter->iSocket[i].bind(controllers[i]->tSocket);
+ for (i = 0; i < Configuration::getInstance().NumberOfMemChannels; i++) {
+ arbiter->iSocket.bind(controllers[i]->tSocket);
controllers[i]->iSocket.bind(drams[i]->tSocket);
}
}
@@ -171,11 +178,10 @@ void inline Simulation::tracePlayerTerminates()
static unsigned int finishedTracePlayers = 0;
finishedTracePlayers++;
- if (finishedTracePlayers == NumberOfTracePlayers)
- {
+ if (finishedTracePlayers == Configuration::getInstance().NumberOfTracePlayers)
terminateSimulation.notify();
- }
}
+
void Simulation::stop()
{
wait(terminateSimulation);
@@ -196,3 +202,4 @@ void Simulation::report(string message)
DebugManager::getInstance().printDebugMessage(this->name(), message);
cout << message << endl;
}
+
diff --git a/dram/src/simulation/Simulation.h b/dram/src/simulation/Simulation.h
index bcc276ed..09b14ad5 100644
--- a/dram/src/simulation/Simulation.h
+++ b/dram/src/simulation/Simulation.h
@@ -86,10 +86,6 @@ public:
void stop();
virtual void tracePlayerTerminates() override;
- // TODO: this information should be get from configuration
- constexpr static unsigned int NumberOfTracePlayers = 4;
- // TODO: this information should be get from configuration
- constexpr static unsigned int NumberOfMemChannels = 1;
private:
std::string traceName;
@@ -101,7 +97,7 @@ private:
// and initiate transactions targeting the memory)
std::vector*> players;
// All transactions pass through the same arbiter
- Arbiter *arbiter;
+ Arbiter<> *arbiter;
// Each DRAM unit has a controller
std::vector*> controllers;
// TODO: Each DRAM has a reorder buffer (check this!)
diff --git a/dram/src/simulation/SimulationManager.cpp b/dram/src/simulation/SimulationManager.cpp
index 396619ad..94909b49 100644
--- a/dram/src/simulation/SimulationManager.cpp
+++ b/dram/src/simulation/SimulationManager.cpp
@@ -162,12 +162,10 @@ void SimulationManager::startTraceAnalyzer()
void SimulationManager::addTraceSetup(SimulationBatch& batch, tinyxml2::XMLElement* element)
{
vector devices;
- for (XMLElement* device = element->FirstChildElement("device"); device != NULL; device = device->NextSiblingElement("device"))
- {
+ for (XMLElement* device = element->FirstChildElement("device"); device != NULL; device = device->NextSiblingElement("device")) {
devices.push_back(Device(device->GetText(), device->IntAttribute("clkMhz"), device->IntAttribute("bl")));
}
- while (devices.size() < Simulation::NumberOfTracePlayers)
- {
+ while (devices.size() < Configuration::getInstance().NumberOfTracePlayers) {
devices.push_back(Device());
}