diff --git a/analyzer/analyzer/paths.pro b/analyzer/analyzer/paths.pro index 102db5af..b19fe4eb 100644 --- a/analyzer/analyzer/paths.pro +++ b/analyzer/analyzer/paths.pro @@ -8,8 +8,8 @@ CONFIG(qwt){ CONFIG(python){ -# LIBS += -L/opt/python/lib -lpython3.4m -# INCLUDEPATH += /opt/python/include/python3.4m - LIBS += -lpython3.3m - INCLUDEPATH += /usr/include/python3.3 + LIBS += -L/opt/python/lib -lpython3.4m + INCLUDEPATH += /opt/python/include/python3.4m +# LIBS += -lpython3.3m +# INCLUDEPATH += /usr/include/python3.3 } diff --git a/dram/dramSys/dramSys.pro b/dram/dramSys/dramSys.pro index c4693944..78ebe06a 100644 --- a/dram/dramSys/dramSys.pro +++ b/dram/dramSys/dramSys.pro @@ -1,4 +1,4 @@ - TEMPLATE = app +TEMPLATE = app CONFIG += console CONFIG -= app_bundle CONFIG -= qt @@ -8,7 +8,7 @@ LIBS += -L/opt/systemc/lib-linux64 -lsystemc LIBS += -L/opt/boost/lib -lboost_filesystem -lboost_system LIBS += -L/opt/sqlite3/lib -lsqlite3 LIBS += -lpthread -LIBS += -L/opt/xerces-c-3.1.1/lib -lxerces-c +LIBS += -L/opt/xerces/lib -lxerces-c LIBS += -L../src/common/third_party/DRAMPower/src/ -ldrampowerxml LIBS += -L../src/common/third_party/DRAMPower/src/ -ldrampower @@ -122,5 +122,6 @@ HEADERS += \ ../src/simulation/Arbiter.h \ ../src/common/libDRAMPower.h \ ../src/controller/core/RowBufferStates.h \ - ../src/controller/scheduler/readwritegrouper.h + ../src/controller/scheduler/readwritegrouper.h \ + ../src/simulation/ReorderBuffer.h diff --git a/dram/resources/configs/amconfigs/am_ddr4 (4th copy).xml b/dram/resources/configs/amconfigs/am_ddr4 (4th copy).xml deleted file mode 100755 index 73d9cb36..00000000 --- a/dram/resources/configs/amconfigs/am_ddr4 (4th copy).xml +++ /dev/null @@ -1,27 +0,0 @@ - - - - - - - - - - - - - diff --git a/dram/resources/configs/memconfigs/fr_fcfs.xml b/dram/resources/configs/memconfigs/fr_fcfs.xml index b126adb1..8aa70731 100644 --- a/dram/resources/configs/memconfigs/fr_fcfs.xml +++ b/dram/resources/configs/memconfigs/fr_fcfs.xml @@ -1,6 +1,6 @@ - + @@ -9,7 +9,6 @@ - diff --git a/dram/resources/simulations/sim-batch.xml b/dram/resources/simulations/sim-batch.xml index 89adea06..516578e6 100644 --- a/dram/resources/simulations/sim-batch.xml +++ b/dram/resources/simulations/sim-batch.xml @@ -1,22 +1,17 @@ WideIO.xml - - am_wideio.xml - - fifo.xml - - + + grouper.xml + + - small.stl + mediabench-fractal_32.stl diff --git a/dram/src/controller/Controller.h b/dram/src/controller/Controller.h index 8a6b9115..e40f8ade 100644 --- a/dram/src/controller/Controller.h +++ b/dram/src/controller/Controller.h @@ -119,10 +119,7 @@ void Controller::buildScheduler() if (selectedScheduler == "FR_FCFS") { - - Scheduler* s = new FR_FCFS(*controllerCore, Configuration::getInstance().RefreshAwareScheduling, - Configuration::getInstance().AdaptiveOpenPagePolicy); - scheduler = new ReadWriteGrouper(s); + scheduler = new FR_FCFS(*controllerCore, Configuration::getInstance().RefreshAwareScheduling,Configuration::getInstance().AdaptiveOpenPagePolicy); } else if (selectedScheduler == "PAR_BS") { @@ -130,7 +127,13 @@ void Controller::buildScheduler() Configuration::getInstance().Capsize); } else if (selectedScheduler == "FIFO") + { scheduler = new Fifo(*controllerCore); + } + else if (selectedScheduler == "Grouper") + { + scheduler = new ReadWriteGrouper(*controllerCore); + } else reportFatal(name(), "unsupported scheduler: " + selectedScheduler); } diff --git a/dram/src/controller/core/configuration/TimingConfiguration.h b/dram/src/controller/core/configuration/TimingConfiguration.h index e990c6fd..cb080c94 100644 --- a/dram/src/controller/core/configuration/TimingConfiguration.h +++ b/dram/src/controller/core/configuration/TimingConfiguration.h @@ -15,8 +15,8 @@ namespace core{ struct RefreshTiming { - RefreshTiming() {}; - RefreshTiming(sc_time tRFC, sc_time tREFI) : tRFC(tRFC), tREFI(tREFI) {}; + RefreshTiming() {} + RefreshTiming(sc_time tRFC, sc_time tREFI) : tRFC(tRFC), tREFI(tREFI) {} sc_time tRFC; sc_time tREFI; }; diff --git a/dram/src/controller/core/scheduling/checker/PrechargeAllChecker.cpp b/dram/src/controller/core/scheduling/checker/PrechargeAllChecker.cpp index 112d4f90..92820e76 100644 --- a/dram/src/controller/core/scheduling/checker/PrechargeAllChecker.cpp +++ b/dram/src/controller/core/scheduling/checker/PrechargeAllChecker.cpp @@ -53,6 +53,12 @@ void PrechargeAllChecker::delayToSatisfyConstraints(ScheduledCommand& command) c } } + ScheduledCommand lastActivate = state.getLastCommand(Command::Activate, command.getBank()); + if (lastActivate.isValidCommand()) + { + command.delayToMeetConstraint(lastActivate.getStart(), config.Timings.tRAS); + } + state.bus.moveCommandToNextFreeSlot(command); } diff --git a/dram/src/controller/scheduler/Fr_Fcfs.cpp b/dram/src/controller/scheduler/Fr_Fcfs.cpp index 5635cc33..b0b6c159 100644 --- a/dram/src/controller/scheduler/Fr_Fcfs.cpp +++ b/dram/src/controller/scheduler/Fr_Fcfs.cpp @@ -97,6 +97,19 @@ unsigned int FR_FCFS::getNumberOfQueuedPayloads() return numberOfQueuedPaylods; } +bool FR_FCFS::containsPayloadTragetingSameAddress(gp *payload) +{ + Bank bank = DramExtension::getExtension(payload).getBank(); + Row row = DramExtension::getExtension(payload).getRow(); + + for(gp* bufferedPayload: buffer[bank]) + { + if(DramExtension::getExtension(bufferedPayload).getRow() == row) + return true; + } + return false; +} + std::vector FR_FCFS::findRowHits(Bank bank, Row row) { vector found; diff --git a/dram/src/controller/scheduler/Fr_Fcfs.h b/dram/src/controller/scheduler/Fr_Fcfs.h index ccfbf718..39446120 100644 --- a/dram/src/controller/scheduler/Fr_Fcfs.h +++ b/dram/src/controller/scheduler/Fr_Fcfs.h @@ -25,6 +25,8 @@ public: gp* popOldest(Bank bank); unsigned int getNumberOfQueuedPayloads(); + //used by read/write grouper + bool containsPayloadTragetingSameAddress(gp* payload); private: std::vector findRowHits(Bank bank, Row row); std::map> buffer; diff --git a/dram/src/controller/scheduler/Scheduler.cpp b/dram/src/controller/scheduler/Scheduler.cpp index b7bbbbb4..a872e821 100644 --- a/dram/src/controller/scheduler/Scheduler.cpp +++ b/dram/src/controller/scheduler/Scheduler.cpp @@ -1,12 +1,16 @@ #include "Scheduler.h" #include "../../common/DebugManager.h" +#include + +using namespace std; using namespace scheduler; std::string Scheduler::sendername = "scheduler"; void Scheduler::printDebugMessage(std::string message) { + //cout << "scheduler: " << message << std::endl; DebugManager::getInstance().printDebugMessage(Scheduler::sendername, message); } diff --git a/dram/src/controller/scheduler/readwritegrouper.cpp b/dram/src/controller/scheduler/readwritegrouper.cpp index 5797fddb..6c2d9306 100644 --- a/dram/src/controller/scheduler/readwritegrouper.cpp +++ b/dram/src/controller/scheduler/readwritegrouper.cpp @@ -1,121 +1,150 @@ #include "readwritegrouper.h" +#include "../../common/DebugManager.h" namespace scheduler{ using namespace tlm; +using namespace std; -ReadWriteGrouper::ReadWriteGrouper(Scheduler *scheduler): - scheduler(scheduler), mode(Mode::read) +ReadWriteGrouper::ReadWriteGrouper(core::ControllerCore& controllerCore): controllerCore(controllerCore) { - + batches.push_back(shared_ptr(new FR_FCFS(controllerCore,true,false))); + batches.push_back(shared_ptr(new FR_FCFS(controllerCore,true,false))); } ReadWriteGrouper::~ReadWriteGrouper() { - delete scheduler; + +} + +void ReadWriteGrouper::schedule(gp *payload) +{ + tlm_command command = payload->get_command(); + + if(batches.size() > 2) + { + if(command == TLM_READ_COMMAND) + { + //printDebugMessage("Scheduling read"); + + if(schedulingReadCausesHazardWithQueuedWrite(payload)) + { + printDebugMessage("Scheduling read causes hazard with queued write"); + batches.push_back(shared_ptr(new FR_FCFS(controllerCore,true,false))); + batches.push_back(shared_ptr(new FR_FCFS(controllerCore,true,false))); + } + + getLatestReadBatch().schedule(payload); + } + else if(command == TLM_WRITE_COMMAND) + { + //printDebugMessage("Scheduling write"); + getLatestWriteBatch().schedule(payload); + } + } + else if(batches.size() == 2) + { + if(command == TLM_READ_COMMAND) + { + //printDebugMessage("Scheduling read"); + + if(getLatestReadBatch().hasPayloads() && schedulingReadCausesHazardWithQueuedWrite(payload)) + { + printDebugMessage("Scheduling read causes hazard with queued write"); + batches.push_back(shared_ptr(new FR_FCFS(controllerCore,true,false))); + batches.push_back(shared_ptr(new FR_FCFS(controllerCore,true,false))); + } + else if(!getLatestReadBatch().hasPayloads() && getLatestWriteBatch().hasPayloads()) + { + printDebugMessage("Scheduling read, but there are writes to be processed first"); + batches.erase(batches.begin()); + batches.push_back(shared_ptr(new FR_FCFS(controllerCore,true,false))); + batches.push_back(shared_ptr(new FR_FCFS(controllerCore,true,false))); + } + getLatestReadBatch().schedule(payload); + + } + else if(command == TLM_WRITE_COMMAND) + { + //printDebugMessage("Scheduling write"); + getLatestWriteBatch().schedule(payload); + } + } + else + { + sc_assert(false); + } +} + +gp *ReadWriteGrouper::getNextPayload() +{ + if(batches.size() > 2) + { + return batches.front()->getNextPayload(); + } + else if(batches.size() == 2) + { + if(getLatestReadBatch().hasPayloads()) + return getLatestReadBatch().getNextPayload(); + else if(getLatestWriteBatch().hasPayloads()) + return getLatestWriteBatch().getNextPayload(); + else + return NULL; + } + else + { + sc_assert(false); + } } void ReadWriteGrouper::removePayload(gp *payload) { - scheduler->removePayload(payload); - - //if scheduler is empty now - if(!scheduler->hasPayloads()) + if(batches.size() > 2) { - if(mode == Mode::read && !writeQueue.empty()) - switchToWriteMode(); - else if(mode == Mode::readToWrite) - switchToWriteMode(); + batches.front()->removePayload(payload); + if(!batches.front()->hasPayloads()) + batches.erase(batches.begin()); + } + else if(batches.size() == 2) + { + if(payload->is_read()) + getLatestReadBatch().removePayload(payload); else - switchToReadMode(); - } -} - -void ReadWriteGrouper::schedule(gp *payload) -{ -tlm_command command = payload->get_command(); - -//in read mode hazards could occur by letting a read pass a queued write -if(mode == Mode::read) -{ - if(command == TLM_READ_COMMAND) - { - //if scheduling the read would cause a hazard switch to readToWriteMode and put the read into the readQueue - if(schedulingReadCausesHazard(payload)) - { - switchToReadToWriteMode(); - readQueue.push_back(payload); - } - else - scheduler->schedule(payload); + getLatestWriteBatch().removePayload(payload); } else { - writeQueue.push_back(payload); - if(!scheduler->hasPayloads()) - //there are no reads in the scheduler, so switch directly to write mode - switchToWriteMode(); + sc_assert(false); } } -else if(mode == Mode::readToWrite) -{ - if(command == TLM_READ_COMMAND) - readQueue.push_back(payload); - else - writeQueue.push_back(payload); -} -else if(mode == Mode::write) -{ - if(command == TLM_READ_COMMAND) - readQueue.push_back(payload); - else - scheduler->schedule(payload); -} -} - -gp *ReadWriteGrouper::getNextPayload() -{ - return scheduler->getNextPayload(); -} bool ReadWriteGrouper::hasPayloads() { - return scheduler->hasPayloads(); + if(batches.size() > 2) + return true; + else if(batches.size() == 2) + return (getLatestReadBatch().hasPayloads() || getLatestWriteBatch().hasPayloads()); + else + sc_assert(false); } -bool ReadWriteGrouper::schedulingReadCausesHazard(gp *payload) +bool ReadWriteGrouper::schedulingReadCausesHazardWithQueuedWrite(gp *payload) { sc_assert(payload->is_read()); - for(gp* write: writeQueue) - { - if(payload->get_address()==write->get_address()) - return true; - } - return false; + return getLatestWriteBatch().containsPayloadTragetingSameAddress(payload); } -void ReadWriteGrouper::switchToReadMode() +FR_FCFS &ReadWriteGrouper::getLatestWriteBatch() { - mode = Mode::read; - for(gp* read: readQueue) - scheduler->schedule(read); - readQueue.clear(); + return *batches[batches.size()-1]; } -void ReadWriteGrouper::switchToWriteMode() +FR_FCFS &ReadWriteGrouper::getLatestReadBatch() { - mode = Mode::write; - for(gp* write: writeQueue) - scheduler->schedule(write); - writeQueue.clear(); -} - -void ReadWriteGrouper::switchToReadToWriteMode() -{ - mode = Mode::readToWrite; + return *batches[batches.size()-2]; } } diff --git a/dram/src/controller/scheduler/readwritegrouper.h b/dram/src/controller/scheduler/readwritegrouper.h index 4e8b359f..dedd0c5d 100644 --- a/dram/src/controller/scheduler/readwritegrouper.h +++ b/dram/src/controller/scheduler/readwritegrouper.h @@ -1,19 +1,18 @@ #ifndef READWRITEGROUPER_H #define READWRITEGROUPER_H #include "Scheduler.h" +#include "Fr_Fcfs.h" +#include "../core/ControllerCore.h" +#include #include + namespace scheduler{ -/* Scheduler that batches reads and writes to reduce the overhead when switching from - * read to write mode (read-to-write constraints) - * The scheduler prioritizes reads. It switches to write mode, when stalling a write would induce a data-hazard - * or when there are no reads to process. - */ class ReadWriteGrouper : public Scheduler { public: - ReadWriteGrouper(Scheduler *scheduler); + ReadWriteGrouper(core::ControllerCore& controllerCore); ~ReadWriteGrouper(); virtual void schedule(gp* payload) override; virtual bool hasPayloads() override; @@ -21,17 +20,19 @@ public: virtual void removePayload(gp* payload) override; private: - Scheduler *scheduler; - std::vector readQueue, writeQueue; - //Mode readToWrite is used to process the remaining reads in the readScheduler before - //switching to write mode (this is used when a potential hazard causes the scheduler to switch modes) - enum class Mode{read,readToWrite, write}; - Mode mode; + // contains batches of requests + // last element always contains writes + // next-to-last element always contains reads + // there are always at least two batches + // if there are more than two batches, batches[0] is never empty and + // getNextPayload and removePayload are forwarded to batches[0] + std::vector> batches; + core::ControllerCore& controllerCore; + + bool schedulingReadCausesHazardWithQueuedWrite(gp* payload); + FR_FCFS& getLatestWriteBatch(); + FR_FCFS& getLatestReadBatch(); - bool schedulingReadCausesHazard(gp* payload); - void switchToReadMode(); - void switchToWriteMode(); - void switchToReadToWriteMode(); }; diff --git a/dram/src/simulation/Arbiter.h b/dram/src/simulation/Arbiter.h index 410ea46c..b7421545 100644 --- a/dram/src/simulation/Arbiter.h +++ b/dram/src/simulation/Arbiter.h @@ -45,10 +45,12 @@ public: private: tlm_utils::peq_with_cb_and_phase payloadEventQueue; bool channelIsFree; - deque backpressure; + //used to account for the request_accept_delay in the dram controllers + deque pendingRequests; + //used to account for the response_accept_delay in the initiators (traceplayer,core etc.) + deque receivedResponses[NUMBER_OF_THREADS]; - - // Initiated by dram + // Initiated by dram side tlm_sync_enum nb_transport_bw(tlm_generic_payload& payload, tlm_phase& phase, sc_time& bwDelay) { TlmRecorder::getInstance().recordPhase(payload, phase, bwDelay + sc_time_stamp()); @@ -56,7 +58,7 @@ private: return TLM_ACCEPTED; } - // Initiated by senders + // Initiated by initiator side tlm_sync_enum nb_transport_fw(int socketId, tlm_generic_payload& payload, tlm_phase& phase, sc_time& fwDelay) { @@ -66,7 +68,9 @@ private: payload.acquire(); } else if(phase == END_RESP) + { payload.release(); + } payloadEventQueue.notify(payload, phase, fwDelay); return TLM_ACCEPTED; @@ -74,6 +78,9 @@ private: void peqCallback(tlm_generic_payload& payload, const tlm_phase& phase) { + unsigned int initiatorSocket = DramExtension::getExtension(payload).getThread().ID()-1; + + //Phases initiated by intiator side if (phase == BEGIN_REQ) { @@ -84,32 +91,40 @@ private: } else { - backpressure.push_back(&payload); + pendingRequests.push_back(&payload); } } else if (phase == END_RESP) { - sendToChannel(payload, phase, SC_ZERO_TIME ); + sendToChannel(payload, phase, SC_ZERO_TIME); + receivedResponses[initiatorSocket].pop_front(); + if(!receivedResponses[initiatorSocket].empty()) + { + tlm_generic_payload* payloadToSend = receivedResponses[initiatorSocket].front(); + sendToInitiator(initiatorSocket,*payloadToSend,BEGIN_RESP,SC_ZERO_TIME); + } } //Phases initiated by dram side else if (phase == END_REQ) { channelIsFree = true; - sendToInitiator(DramExtension::getExtension(payload).getThread().ID()-1, payload, phase, SC_ZERO_TIME); + sendToInitiator(initiatorSocket, payload, phase, SC_ZERO_TIME); - if(!backpressure.empty()) + if(!pendingRequests.empty()) { - tlm_generic_payload* payloadToSend = backpressure.front(); - backpressure.pop_front(); + tlm_generic_payload* payloadToSend = pendingRequests.front(); + pendingRequests.pop_front(); sendToChannel(*payloadToSend, BEGIN_REQ, SC_ZERO_TIME ); channelIsFree = false; } } else if (phase == BEGIN_RESP) - { - sendToInitiator(DramExtension::getExtension(payload).getThread().ID()-1, payload, phase, SC_ZERO_TIME); + { + if(receivedResponses[initiatorSocket].empty()) + sendToInitiator(initiatorSocket, payload, phase, SC_ZERO_TIME); + receivedResponses[initiatorSocket].push_back(&payload); } else @@ -136,7 +151,7 @@ private: { 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), + DramExtension* extension = new DramExtension(Thread(socketId+1), Channel(0), Bank(decodedAddress.bank), BankGroup(decodedAddress.bankgroup), Row(decodedAddress.row), Column(decodedAddress.column),burstlength); payload.set_auto_extension(extension); } diff --git a/dram/src/simulation/Dram.h b/dram/src/simulation/Dram.h index 22e48d74..9b306f27 100644 --- a/dram/src/simulation/Dram.h +++ b/dram/src/simulation/Dram.h @@ -30,7 +30,7 @@ using namespace core; using namespace Data; -#define POWER +#define POWER //not better to define in simulation xml? also flag for storage simulation #ifdef POWER #define IFPOW(x) x @@ -39,43 +39,6 @@ using namespace Data; #endif -class column -{ - private: - - unsigned char * data; - unsigned int bytes; - - public: - - column() - { - bytes = 0; - data = NULL; - } - - column(int bytes) - { - this->bytes = bytes; - data = new unsigned char[bytes]; - } - - ~column() - { - delete data; - } - - void set(unsigned char * payloadDataPtr) - { - memcpy(data, payloadDataPtr, bytes); - } - - void get(unsigned char * payloadDataPtr) - { - memcpy(payloadDataPtr, data, bytes); - } -}; - template struct Dram: sc_module @@ -83,7 +46,7 @@ struct Dram: sc_module tlm_utils::simple_target_socket tSocket; IFPOW(libDRAMPower *DRAMPower); - map< unsigned long int, column * > memory; + map< unsigned long int, unsigned char[BUSWIDTH/2] > memory; SC_CTOR(Dram) : tSocket("socket") { @@ -128,28 +91,24 @@ struct Dram: sc_module else if (phase == BEGIN_WR) { IFPOW(DRAMPower->doCommand(MemCommand::WR, bank, cycle)); + //save data: + memcpy(&memory[payload.get_address()], payload.get_data_ptr(), BUSWIDTH/8); sendToController(payload, END_WR, delay + getExecutionTime(Command::Write, payload)); - - // Save: - //column * c = new column(16); - //c->set(payload.get_data_ptr()); - //memory[payload.get_address()] = c; } else if (phase == BEGIN_RD) { IFPOW(DRAMPower->doCommand(MemCommand::RD, bank, cycle)); sendToController(payload, END_RD, delay + getExecutionTime(Command::Read, payload)); - // Load: - //if(memory.count(payload.get_address()) == 1) - //{ - // column * c = memory[payload.get_address()]; - // c->get(payload.get_data_ptr()); - //} - //else - //{ - // SC_REPORT_WARNING ("DRAM", "Reading from an empty memory location"); - //} + // Load data: + if(memory.count(payload.get_address()) == 1) + { + memcpy(payload.get_data_ptr(), &memory[payload.get_address()], BUSWIDTH/8); + } + else + { + //SC_REPORT_WARNING ("DRAM", "Reading from an empty memory location."); + } } else if (phase == BEGIN_WRA) { diff --git a/dram/src/simulation/ReorderBuffer.h b/dram/src/simulation/ReorderBuffer.h new file mode 100644 index 00000000..82a74b4b --- /dev/null +++ b/dram/src/simulation/ReorderBuffer.h @@ -0,0 +1,133 @@ +#ifndef REORDERBUFFER_H +#define REORDERBUFFER_H + +#include +#include +#include + +using namespace std; +using namespace tlm; + +template +struct ReorderBuffer: public sc_module +{ +public: + tlm_utils::simple_initiator_socket iSocket; + tlm_utils::simple_target_socket tSocket; + + SC_CTOR(ReorderBuffer) : + payloadEventQueue(this, &ReorderBuffer::peqCallback), responseIsPendingInInitator(false) + { + iSocket.register_nb_transport_bw(this, &ReorderBuffer::nb_transport_bw); + tSocket.register_nb_transport_fw(this, &ReorderBuffer::nb_transport_fw); + } + +private: + tlm_utils::peq_with_cb_and_phase payloadEventQueue; + deque pendingRequestsInOrder; + set receivedResponses; + + bool responseIsPendingInInitator; + + + // Initiated by dram side + tlm_sync_enum nb_transport_bw(tlm_generic_payload& payload, tlm_phase& phase, sc_time& bwDelay) + { + payloadEventQueue.notify(payload, phase, bwDelay); + return TLM_ACCEPTED; + } + + // Initiated by initator side (players) + tlm_sync_enum nb_transport_fw(tlm_generic_payload& payload, tlm_phase& phase, + sc_time& fwDelay) + { + if (phase == BEGIN_REQ) + { + payload.acquire(); + } + else if (phase == END_RESP) + { + payload.release(); + } + + payloadEventQueue.notify(payload, phase, fwDelay); + return TLM_ACCEPTED; + } + + void peqCallback(tlm_generic_payload& payload, const tlm_phase& phase) + { + //Phases initiated by initiator side + if (phase == BEGIN_REQ) + { + pendingRequestsInOrder.push_back(&payload); + sendToTarget(payload, phase, SC_ZERO_TIME ); + } + + else if (phase == END_RESP) + { + responseIsPendingInInitator = false; + pendingRequestsInOrder.pop_front(); + receivedResponses.erase(&payload); + sendNextResponse(); + } + + //Phases initiated by dram side + else if (phase == END_REQ) + { + sendToInitiator(payload, phase, SC_ZERO_TIME); + } + else if (phase == BEGIN_RESP) + { + sendToTarget(payload, END_RESP, SC_ZERO_TIME); + receivedResponses.emplace(&payload); + sendNextResponse(); + } + + + else + { + SC_REPORT_FATAL(0, "Payload event queue in arbiter was triggered with unknown 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); + } + + void sendToInitiator(tlm_generic_payload& payload, const tlm_phase& phase, const sc_time& delay) + { + + + sc_assert(phase == END_REQ || + (phase == BEGIN_RESP && pendingRequestsInOrder.front() == &payload && receivedResponses.count(&payload))); + + tlm_phase TPhase = phase; + sc_time TDelay = delay; + tSocket->nb_transport_bw(payload, TPhase, TDelay); + } + + void sendNextResponse() + { + //only send the next response when there response for the oldest pending request (requestsInOrder.front()) + //has been received + if(!responseIsPendingInInitator && receivedResponses.count(pendingRequestsInOrder.front())) + { + tlm_generic_payload* payloadToSend = pendingRequestsInOrder.front(); + responseIsPendingInInitator = true; + sendToInitiator(*payloadToSend,BEGIN_RESP,SC_ZERO_TIME); + } +// else if(!responseIsPendingInInitator && receivedResponses.size()>0 && !receivedResponses.count(pendingRequestsInOrder.front())>0) +// { +// cout << "cant send this response, because we are still waiting for response of oldest pending request. Elemts in buffer: " << receivedResponses.size() << endl; +// } + } + +}; + + + + +#endif // REORDERBUFFER_H diff --git a/dram/src/simulation/Simulation.cpp b/dram/src/simulation/Simulation.cpp index 31507a77..019fb56a 100644 --- a/dram/src/simulation/Simulation.cpp +++ b/dram/src/simulation/Simulation.cpp @@ -44,14 +44,14 @@ void Simulation::setupDebugManager(const string& traceName) { auto& dbg = DebugManager::getInstance(); -// dbg.addToWhiteList(controller->name()); -// dbg.addToWhiteList(player2->name()); -// dbg.addToWhiteList(player1->name()); -// dbg.addToWhiteList(this->name()); -// dbg.addToWhiteList(Scheduler::sendername); -// dbg.addToWhiteList(TlmRecorder::senderName); -// dbg.addToWhiteList(ControllerCore::senderName); -// dbg.addToWhiteList(PowerDownManagerBankwise::senderName); + dbg.addToWhiteList(controller->name()); + dbg.addToWhiteList(player2->name()); + dbg.addToWhiteList(player1->name()); + dbg.addToWhiteList(this->name()); + dbg.addToWhiteList(Scheduler::sendername); + dbg.addToWhiteList(TlmRecorder::senderName); + dbg.addToWhiteList(ControllerCore::senderName); + dbg.addToWhiteList(PowerDownManagerBankwise::senderName); dbg.writeToConsole = true; dbg.writeToFile = true; @@ -82,6 +82,7 @@ void Simulation::instantiateModules(const string &pathToResources, const std::ve dram = new Dram<>("dram"); arbiter = new Arbiter("arbiter"); controller = new Controller<>("controller"); + reorder = new ReorderBuffer<>("reorder"); player1 = new TracePlayer<>("player1", pathToResources + string("traces/") + devices[0].trace, devices[0].burstLength, devices[0].clkMhz, this); player2 = new TracePlayer<>("player2", pathToResources + string("traces/") + devices[1].trace, devices[1].burstLength, devices[1].clkMhz, this); @@ -91,7 +92,10 @@ void Simulation::instantiateModules(const string &pathToResources, const std::ve void Simulation::bindSockets() { - player1->iSocket.bind(arbiter->tSockets[0]); + //player1->iSocket.bind(arbiter->tSockets[0]); + player1->iSocket.bind(reorder->tSocket); + reorder->iSocket.bind(arbiter->tSockets[0]); + player2->iSocket.bind(arbiter->tSockets[1]); player3->iSocket.bind(arbiter->tSockets[2]); player4->iSocket.bind(arbiter->tSockets[3]); diff --git a/dram/src/simulation/Simulation.h b/dram/src/simulation/Simulation.h index 1075291f..8b4d5dc0 100644 --- a/dram/src/simulation/Simulation.h +++ b/dram/src/simulation/Simulation.h @@ -11,6 +11,7 @@ #include "Dram.h" #include "Arbiter.h" #include "TracePlayer.h" +#include "ReorderBuffer.h" #include "../controller/Controller.h" #include "ISimulation.h" #include @@ -61,6 +62,7 @@ private: Dram<> *dram; Arbiter *arbiter; Controller<> *controller; + ReorderBuffer<> *reorder; TracePlayer<> *player1; TracePlayer<> *player2; diff --git a/dram/src/simulation/SimulationManager.cpp b/dram/src/simulation/SimulationManager.cpp index 3e2fb5de..d5201ed7 100644 --- a/dram/src/simulation/SimulationManager.cpp +++ b/dram/src/simulation/SimulationManager.cpp @@ -1,4 +1,4 @@ -/* + /* * SimulationManager.cpp * * Created on: Apr 12, 2014 diff --git a/dram/src/simulation/TracePlayer.h b/dram/src/simulation/TracePlayer.h index 5581ed6c..db699b53 100644 --- a/dram/src/simulation/TracePlayer.h +++ b/dram/src/simulation/TracePlayer.h @@ -33,7 +33,7 @@ struct TracePlayer: public sc_module public: tlm_utils::simple_initiator_socket iSocket; TracePlayer(sc_module_name /*name*/, string pathToTrace, unsigned int burstLength, unsigned int clkMhz, - simulation::ISimulation* simulationManager); + simulation::ISimulation* simulationManager); void start(); @@ -85,72 +85,148 @@ void TracePlayer::start() template void TracePlayer::generateNextPayload() { - if (file) + + if(file) { - string time, command, address, data; - file >> time >> command >> address; - - //if there is a newline at the end of the .stl - if (time.empty() || command.empty() || address.empty() ) - return; - - long parsedAdress = std::stoi(address.c_str(), 0, 16); - - gp* payload = memoryManager.allocate(); - payload->set_address(parsedAdress); - - // Set data pointer - unsigned char * dataElement = new unsigned char[16]; // TODO: column / burst breite - payload->set_data_length(16); // TODO: column / burst breite - payload->set_data_ptr(dataElement); - for(int i = 0; i < 16; i++) // TODO: column / burst breite - dataElement[i] = 0; - - if (command == "read") + string line; + if (std::getline(file, line)) { - payload->set_command(TLM_READ_COMMAND); - } - else if (command == "write") - { - payload->set_command(TLM_WRITE_COMMAND); + std::istringstream iss(line); + string time, command, address; + iss >> time >> command >> address; + if (time.empty() || command.empty() || address.empty() ) + return; + long parsedAdress = std::stoi(address.c_str(), 0, 16); - // Parse and set data - file >> data; - unsigned int counter = 0; - for(int i = 0; i < 16*2-2; i=i+2) // TODO column / burst breite + gp* payload = memoryManager.allocate(); + payload->set_address(parsedAdress); + + // Set data pointer + unsigned char * dataElement = new unsigned char[16]; // TODO: column / burst breite + payload->set_data_length(16); // TODO: column / burst breite + payload->set_data_ptr(dataElement); + for(int i = 0; i < 16; i++) // TODO: column / burst breite + dataElement[i] = 0; + + if (command == "read") { - std::string byteString = "0x"; - byteString.append(data.substr(i+2, 2)); - //cout << byteString << " " << std::stoi(byteString.c_str(), 0, 16) << endl; - dataElement[counter++] = std::stoi(byteString.c_str(), 0, 16); + payload->set_command(TLM_READ_COMMAND); } - } - else - { - SC_REPORT_FATAL(0, - (string("Corrupted tracefile, command ") + command + string(" unknown")).c_str()); - } + else if (command == "write") + { + payload->set_command(TLM_WRITE_COMMAND); - payload->set_response_status(TLM_INCOMPLETE_RESPONSE); - payload->set_dmi_allowed(false); - payload->set_byte_enable_length(0); - payload->set_streaming_width(burstlenght); + // Parse and set data + string data; + iss >> data; - sc_time sendingTime = std::stoi(time.c_str())*clk; - GenerationExtension* genExtension = new GenerationExtension(sendingTime); - payload->set_auto_extension(genExtension); + if(!data.empty()) + { + //cout << "parsing write data: " << data << std::endl; + + for(int i = 0; i < 16; i++) // TODO column / burst breite + { + std::string byteString = "0x"; + byteString.append(data.substr(2*(i+1), 2)); + //cout << byteString << " " << std::stoi(byteString.c_str(), 0, 16) << endl; + dataElement[i] = std::stoi(byteString.c_str(), 0, 16); + } + } + } + else + { + SC_REPORT_FATAL(0, + (string("Corrupted tracefile, command ") + command + string(" unknown")).c_str()); + } + + payload->set_response_status(TLM_INCOMPLETE_RESPONSE); + payload->set_dmi_allowed(false); + payload->set_byte_enable_length(0); + payload->set_streaming_width(burstlenght); + + sc_time sendingTime = std::stoi(time.c_str())*clk; + GenerationExtension* genExtension = new GenerationExtension(sendingTime); + payload->set_auto_extension(genExtension); + + if (sendingTime <= sc_time_stamp()) + { + payloadEventQueue.notify(*payload, BEGIN_REQ, SC_ZERO_TIME); + } + else + { + payloadEventQueue.notify(*payload, BEGIN_REQ, sendingTime - sc_time_stamp()); + } + numberOfPendingTransactions++; - if (sendingTime <= sc_time_stamp()) - { - payloadEventQueue.notify(*payload, BEGIN_REQ, SC_ZERO_TIME); } - else - { - payloadEventQueue.notify(*payload, BEGIN_REQ, sendingTime - sc_time_stamp()); - } - numberOfPendingTransactions++; } } + // if (file) + // { + // string time, command, address, data; + // file >> time >> command >> address; + + // //if there is a newline at the end of the .stl + // if (time.empty() || command.empty() || address.empty() ) + // return; + + // long parsedAdress = std::stoi(address.c_str(), 0, 16); + + // gp* payload = memoryManager.allocate(); + // payload->set_address(parsedAdress); + + // // Set data pointer + // unsigned char * dataElement = new unsigned char[16]; // TODO: column / burst breite + // payload->set_data_length(16); // TODO: column / burst breite + // payload->set_data_ptr(dataElement); + // for(int i = 0; i < 16; i++) // TODO: column / burst breite + // dataElement[i] = 0; + + // if (command == "read") + // { + // payload->set_command(TLM_READ_COMMAND); + // } + // else if (command == "write") + // { + // payload->set_command(TLM_WRITE_COMMAND); + + // // Parse and set data + //// file >> data; + //// unsigned int counter = 0; + //// for(int i = 0; i < 16*2-2; i=i+2) // TODO column / burst breite + //// { + //// std::string byteString = "0x"; + //// byteString.append(data.substr(i+2, 2)); + //// //cout << byteString << " " << std::stoi(byteString.c_str(), 0, 16) << endl; + //// dataElement[counter++] = std::stoi(byteString.c_str(), 0, 16); + //// } + // } + // else + // { + // SC_REPORT_FATAL(0, + // (string("Corrupted tracefile, command ") + command + string(" unknown")).c_str()); + // } + + // payload->set_response_status(TLM_INCOMPLETE_RESPONSE); + // payload->set_dmi_allowed(false); + // payload->set_byte_enable_length(0); + // payload->set_streaming_width(burstlenght); + + // sc_time sendingTime = std::stoi(time.c_str())*clk; + // GenerationExtension* genExtension = new GenerationExtension(sendingTime); + // payload->set_auto_extension(genExtension); + + // if (sendingTime <= sc_time_stamp()) + // { + // payloadEventQueue.notify(*payload, BEGIN_REQ, SC_ZERO_TIME); + // } + // else + // { + // payloadEventQueue.notify(*payload, BEGIN_REQ, sendingTime - sc_time_stamp()); + // } + // numberOfPendingTransactions++; + // } +//} template tlm_sync_enum TracePlayer::nb_transport_bw(tlm_generic_payload &payload, tlm_phase &phase, sc_time &bwDelay)