From 9985b9175e4ac4dbfcf660cd4394db921178a80e Mon Sep 17 00:00:00 2001 From: Matthias Jung Date: Wed, 19 Jul 2017 10:37:00 +0300 Subject: [PATCH 1/5] Changed FR_FCFS_RP Scheduler Added hazard detection and simplification of the code. --- .../configs/mcconfigs/fr_fcfs_rp.xml | 2 +- .../src/controller/scheduler/Fr_Fcfs.h | 2 +- .../scheduler/Fr_Fcfs_read_priority.cpp | 128 +++++++++++------- .../scheduler/Fr_Fcfs_read_priority.h | 3 +- 4 files changed, 82 insertions(+), 53 deletions(-) diff --git a/DRAMSys/simulator/resources/configs/mcconfigs/fr_fcfs_rp.xml b/DRAMSys/simulator/resources/configs/mcconfigs/fr_fcfs_rp.xml index caa9ff67..68b2799c 100644 --- a/DRAMSys/simulator/resources/configs/mcconfigs/fr_fcfs_rp.xml +++ b/DRAMSys/simulator/resources/configs/mcconfigs/fr_fcfs_rp.xml @@ -1,7 +1,7 @@ - + diff --git a/DRAMSys/simulator/src/controller/scheduler/Fr_Fcfs.h b/DRAMSys/simulator/src/controller/scheduler/Fr_Fcfs.h index 3b2450de..ece2b5b4 100644 --- a/DRAMSys/simulator/src/controller/scheduler/Fr_Fcfs.h +++ b/DRAMSys/simulator/src/controller/scheduler/Fr_Fcfs.h @@ -57,9 +57,9 @@ public: protected: std::map> buffer; + std::deque::iterator FindRowHit(Bank bank); private: - std::deque::iterator FindRowHit(Bank bank); }; diff --git a/DRAMSys/simulator/src/controller/scheduler/Fr_Fcfs_read_priority.cpp b/DRAMSys/simulator/src/controller/scheduler/Fr_Fcfs_read_priority.cpp index 750bfc92..57f17426 100644 --- a/DRAMSys/simulator/src/controller/scheduler/Fr_Fcfs_read_priority.cpp +++ b/DRAMSys/simulator/src/controller/scheduler/Fr_Fcfs_read_priority.cpp @@ -40,72 +40,100 @@ std::pair FR_FCFS_RP::getNextRequest(Bank bank) { - // If the bank is empty like Bank0 in the example we do nothing + // If the bank is empty like Bank0 in the example we do nothing: if(buffer[bank].empty()) { return pair(Command::NOP, NULL); } - // In FR_FCFS row hits have always the highest priority, therefore we search - // for row hits. If we find a row hit, we remove the transaction from the - // queue and send it to the DRAM. - deque::iterator it = FindRowHit_RP(bank); - if(it != buffer[bank].end()) + // Order of Priority: + // 1. Read Hits (Hazard Check) + // 2. Write Hits + // 3. Read Miss (Hazard Check) TODO + // 4. Write Miss TODO + + if(DebugManager::getInstance().writeToConsole == true) { - gp* payload = *it; - buffer[bank].erase(it); - return pair(getReadWriteCommand(*payload), payload); + for(unsigned long i=0; i < buffer[bank].size(); i++) + { + gp* trans = buffer[bank].at(i); + cout << ((trans->get_command() == tlm::TLM_READ_COMMAND)?"R":"W"); + } + cout << endl; + cout.flush(); } - // If there is no row hit, the FR_FCFS takes always the oldest transaction - // in the buffer, i.e. the transaction in the front. + // 1. Seach for read hit: + for(unsigned long i=0; i < buffer[bank].size(); i++) + { + gp* read = buffer[bank].at(i); + + if(read->get_command() == tlm::TLM_READ_COMMAND) + { + // If there is a row hit: + if(DramExtension::getRow(read) + == controllerCore.getRowBufferStates().getRowInRowBuffer(bank)) + { + if(hazardDetection(bank, i) == false) + { + buffer[bank].erase(buffer[bank].begin() + i); + return pair(getReadWriteCommand(*read), + read); + } + } + } + } + + // 2. Search for write hit: + for(unsigned long i=0; i < buffer[bank].size(); i++) + { + gp* write = buffer[bank].at(i); + + if(write->get_command() == tlm::TLM_WRITE_COMMAND) + { + // If there is a row hit: + if(DramExtension::getRow(write) + == controllerCore.getRowBufferStates().getRowInRowBuffer(bank)) + { + buffer[bank].erase(buffer[bank].begin() + i); + return pair(getReadWriteCommand(*write), + write); + } + } + } + + // For now return the oldest request. TODO: do read first! return pair(getNextCommand(buffer[bank].front()), buffer[bank].front()); + + reportFatal("FR_FCFS_RP", "Never should go here ..."); } -// This function searches for a row hit in the scheduling queue of the specific -// bank like FindRowHit in FR_FCFS. However, it will search for reads first and -// it will take a write only if there is no read row hit. -// If no row hit is found the end of the queue is returned. -// -// Note: end() Returns an iterator referring to the past-the-end element in the -// deque container. The past-the-end element is the theoretical element that -// would follow the last element in the deque container. It does not point to -// any element, and thus shall not be dereferenced. -deque::iterator FR_FCFS_RP::FindRowHit_RP(Bank bank) +// There is a hazard if a read is found which will be scheduled before a write +// to the same column and the same row of the same bank: +bool FR_FCFS_RP::hazardDetection(Bank bank, unsigned long id) { - deque &queue = buffer[bank]; + gp* read = buffer[bank].at(id); - if(!controllerCore.getRowBufferStates().rowBufferIsOpen(bank)) - return queue.end(); - - // Traverse the scheduling queue of the specific - // bank and serach for read hits: - for(auto it = queue.begin(); it!=queue.end(); it++) + for(unsigned long i=0; i < id; i++) { - gp* payload = *it; - //Found read row-hit and return the according iterator - if(DramExtension::getRow(payload) - == controllerCore.getRowBufferStates().getRowInRowBuffer(bank) - && payload->get_command() == tlm::TLM_READ_COMMAND) + gp* write = buffer[bank].at(i); + if(write->get_command() == tlm::TLM_WRITE_COMMAND) { - return it; + if((DramExtension::getExtension(read).getColumn() + == DramExtension::getExtension(write).getColumn()) + && (DramExtension::getExtension(read).getRow() + == DramExtension::getExtension(write).getRow())) + { + printDebugMessage("Hazard Detected"); + return true; + } } } - // Traverse the scheduling queue of the specific - // bank and serach for write hits in case no read was found: - for(auto it = queue.begin(); it!=queue.end(); it++) - { - gp* payload = *it; - //Found read row-hit and return the according iterator - if(DramExtension::getRow(payload) - == controllerCore.getRowBufferStates().getRowInRowBuffer(bank) - && payload->get_command() == tlm::TLM_WRITE_COMMAND) - { - return it; - } - } - - // If neither read or write hit was found we return the end: - return queue.end(); + return false; +} + +void FR_FCFS_RP::printDebugMessage(std::string message) +{ + DebugManager::getInstance().printDebugMessage("FR_FCFS_RP", message); } diff --git a/DRAMSys/simulator/src/controller/scheduler/Fr_Fcfs_read_priority.h b/DRAMSys/simulator/src/controller/scheduler/Fr_Fcfs_read_priority.h index d0cab41c..1593a517 100644 --- a/DRAMSys/simulator/src/controller/scheduler/Fr_Fcfs_read_priority.h +++ b/DRAMSys/simulator/src/controller/scheduler/Fr_Fcfs_read_priority.h @@ -48,7 +48,8 @@ public: private: - std::deque::iterator FindRowHit_RP(Bank bank); + bool hazardDetection(Bank bank, unsigned long id); + void printDebugMessage(std::string message); }; #endif // FR_FCFS_READ_PRIORITY_H From e3450687c8b24b7b00ab5203648b8d6029c657bc Mon Sep 17 00:00:00 2001 From: Matthias Jung Date: Wed, 19 Jul 2017 11:22:46 +0300 Subject: [PATCH 2/5] Changed FR_FCFS_RP to C++11 style --- .../scheduler/Fr_Fcfs_read_priority.cpp | 42 +++++++------------ .../scheduler/Fr_Fcfs_read_priority.h | 2 +- 2 files changed, 16 insertions(+), 28 deletions(-) diff --git a/DRAMSys/simulator/src/controller/scheduler/Fr_Fcfs_read_priority.cpp b/DRAMSys/simulator/src/controller/scheduler/Fr_Fcfs_read_priority.cpp index 57f17426..92c07c63 100644 --- a/DRAMSys/simulator/src/controller/scheduler/Fr_Fcfs_read_priority.cpp +++ b/DRAMSys/simulator/src/controller/scheduler/Fr_Fcfs_read_priority.cpp @@ -52,21 +52,10 @@ std::pair FR_FCFS_RP::getNextRequest(Bank bank) // 3. Read Miss (Hazard Check) TODO // 4. Write Miss TODO - if(DebugManager::getInstance().writeToConsole == true) - { - for(unsigned long i=0; i < buffer[bank].size(); i++) - { - gp* trans = buffer[bank].at(i); - cout << ((trans->get_command() == tlm::TLM_READ_COMMAND)?"R":"W"); - } - cout << endl; - cout.flush(); - } - // 1. Seach for read hit: - for(unsigned long i=0; i < buffer[bank].size(); i++) + for(auto it = buffer[bank].begin(); it!=buffer[bank].end(); it++) { - gp* read = buffer[bank].at(i); + gp* read = *it; if(read->get_command() == tlm::TLM_READ_COMMAND) { @@ -74,20 +63,19 @@ std::pair FR_FCFS_RP::getNextRequest(Bank bank) if(DramExtension::getRow(read) == controllerCore.getRowBufferStates().getRowInRowBuffer(bank)) { - if(hazardDetection(bank, i) == false) + if(hazardDetection(bank, it) == false) { - buffer[bank].erase(buffer[bank].begin() + i); - return pair(getReadWriteCommand(*read), - read); + buffer[bank].erase(it); + return pair(getReadWriteCommand(*read),read); } } } } - // 2. Search for write hit: - for(unsigned long i=0; i < buffer[bank].size(); i++) + // 2. Seach for write hit: + for(auto it = buffer[bank].begin(); it!=buffer[bank].end(); it++) { - gp* write = buffer[bank].at(i); + gp* write = *it; if(write->get_command() == tlm::TLM_WRITE_COMMAND) { @@ -95,9 +83,8 @@ std::pair FR_FCFS_RP::getNextRequest(Bank bank) if(DramExtension::getRow(write) == controllerCore.getRowBufferStates().getRowInRowBuffer(bank)) { - buffer[bank].erase(buffer[bank].begin() + i); - return pair(getReadWriteCommand(*write), - write); + buffer[bank].erase(it); + return pair(getReadWriteCommand(*write),write); } } } @@ -111,13 +98,14 @@ std::pair FR_FCFS_RP::getNextRequest(Bank bank) // There is a hazard if a read is found which will be scheduled before a write // to the same column and the same row of the same bank: -bool FR_FCFS_RP::hazardDetection(Bank bank, unsigned long id) +bool FR_FCFS_RP::hazardDetection(Bank bank, std::deque::iterator ext) { - gp* read = buffer[bank].at(id); + gp* read = *ext; - for(unsigned long i=0; i < id; i++) + //for(unsigned long i=0; i < id; i++) + for(auto it = buffer[bank].begin(); it!=ext; it++) { - gp* write = buffer[bank].at(i); + gp* write = *it; if(write->get_command() == tlm::TLM_WRITE_COMMAND) { if((DramExtension::getExtension(read).getColumn() diff --git a/DRAMSys/simulator/src/controller/scheduler/Fr_Fcfs_read_priority.h b/DRAMSys/simulator/src/controller/scheduler/Fr_Fcfs_read_priority.h index 1593a517..1b00d732 100644 --- a/DRAMSys/simulator/src/controller/scheduler/Fr_Fcfs_read_priority.h +++ b/DRAMSys/simulator/src/controller/scheduler/Fr_Fcfs_read_priority.h @@ -48,7 +48,7 @@ public: private: - bool hazardDetection(Bank bank, unsigned long id); + bool hazardDetection(Bank bank, std::deque::iterator ext); void printDebugMessage(std::string message); }; From 3c2efc285df4888f4a341c5002591180ea86184c Mon Sep 17 00:00:00 2001 From: Matthias Jung Date: Wed, 19 Jul 2017 11:53:27 +0300 Subject: [PATCH 3/5] Read before write in miss scenarios for FR_FCFS_RP --- .../scheduler/Fr_Fcfs_read_priority.cpp | 39 ++++++++++++++++--- 1 file changed, 33 insertions(+), 6 deletions(-) diff --git a/DRAMSys/simulator/src/controller/scheduler/Fr_Fcfs_read_priority.cpp b/DRAMSys/simulator/src/controller/scheduler/Fr_Fcfs_read_priority.cpp index 92c07c63..57a5b7b3 100644 --- a/DRAMSys/simulator/src/controller/scheduler/Fr_Fcfs_read_priority.cpp +++ b/DRAMSys/simulator/src/controller/scheduler/Fr_Fcfs_read_priority.cpp @@ -49,8 +49,8 @@ std::pair FR_FCFS_RP::getNextRequest(Bank bank) // Order of Priority: // 1. Read Hits (Hazard Check) // 2. Write Hits - // 3. Read Miss (Hazard Check) TODO - // 4. Write Miss TODO + // 3. Read Miss (Hazard Check) + // 4. Write Miss // 1. Seach for read hit: for(auto it = buffer[bank].begin(); it!=buffer[bank].end(); it++) @@ -66,13 +66,14 @@ std::pair FR_FCFS_RP::getNextRequest(Bank bank) if(hazardDetection(bank, it) == false) { buffer[bank].erase(it); + printDebugMessage("Read Hit found"); return pair(getReadWriteCommand(*read),read); } } } } - // 2. Seach for write hit: + // 2. Search for write hit: for(auto it = buffer[bank].begin(); it!=buffer[bank].end(); it++) { gp* write = *it; @@ -84,14 +85,40 @@ std::pair FR_FCFS_RP::getNextRequest(Bank bank) == controllerCore.getRowBufferStates().getRowInRowBuffer(bank)) { buffer[bank].erase(it); + printDebugMessage("Write Hit found"); return pair(getReadWriteCommand(*write),write); } } } - // For now return the oldest request. TODO: do read first! - return pair(getNextCommand(buffer[bank].front()), - buffer[bank].front()); + // For now return the oldest request but prefere also reads before writes: + + // 3. Search for read miss: + for(auto it = buffer[bank].begin(); it!=buffer[bank].end(); it++) + { + gp* read = *it; + + if(read->get_command() == tlm::TLM_READ_COMMAND) + { + if(hazardDetection(bank, it) == false) + { + printDebugMessage("Read miss found"); + return pair(getNextCommand(read),read); + } + } + } + + // 3. Search for write miss: + for(auto it = buffer[bank].begin(); it!=buffer[bank].end(); it++) + { + gp* write = *it; + + if(write->get_command() == tlm::TLM_WRITE_COMMAND) + { + printDebugMessage("Write miss found"); + return pair(getNextCommand(write),write); + } + } reportFatal("FR_FCFS_RP", "Never should go here ..."); } From 0cfe391113203e8bb4142b51315d141e290a8542 Mon Sep 17 00:00:00 2001 From: Matthias Jung Date: Wed, 19 Jul 2017 12:07:26 +0300 Subject: [PATCH 4/5] Added an address offset to the gem5 setup --- DRAMSys/gem5/main.cpp | 87 ++++++++++++++++++++++++++++++++++++++++--- 1 file changed, 82 insertions(+), 5 deletions(-) diff --git a/DRAMSys/gem5/main.cpp b/DRAMSys/gem5/main.cpp index d166627f..d75ef171 100644 --- a/DRAMSys/gem5/main.cpp +++ b/DRAMSys/gem5/main.cpp @@ -55,7 +55,7 @@ class Gem5SimControlDRAMsys: public Gem5SystemC::Gem5SimControl { public: Gem5SimControlDRAMsys(string configFile) : - Gem5SystemC::Gem5SimControl("gem5",configFile,0,"") + Gem5SystemC::Gem5SimControl("gem5",configFile,0,"MemoryAccess") { } @@ -65,6 +65,60 @@ public: } }; + +struct AddressOffset: sc_module +{ + private: + unsigned long long int offset; + + public: + tlm_utils::simple_target_socket t_socket; + tlm_utils::simple_initiator_socket i_socket; + + AddressOffset(sc_module_name, unsigned long long int o) : offset(o),t_socket("t_socket"),i_socket("i_socket") + { + t_socket.register_nb_transport_fw(this,&AddressOffset::nb_transport_fw); + t_socket.register_transport_dbg(this,&AddressOffset::transport_dbg); + t_socket.register_b_transport(this,&AddressOffset::b_transport); + i_socket.register_nb_transport_bw(this,&AddressOffset::nb_transport_bw); + } + + //Forward Interface + tlm::tlm_sync_enum nb_transport_fw(tlm_generic_payload &trans, tlm_phase &phase, sc_time &delay) + { + //std::cout << "NB "<< this->name() <<": " << trans.get_address() << " -" << offset; + trans.set_address(trans.get_address()-offset); + //std::cout << " = " << trans.get_address() << std::endl; + return i_socket->nb_transport_fw(trans,phase,delay); + } + + unsigned int transport_dbg(tlm::tlm_generic_payload &trans) + { + // adjust address offset: + //std::cout << "Debug "<< this->name() <<": " << trans.get_address() << " -" << offset; + trans.set_address(trans.get_address()-offset); + //std::cout << " = " << trans.get_address() << std::endl; + return i_socket->transport_dbg(trans); + } + + void b_transport(tlm::tlm_generic_payload &trans, sc_time &delay) + { + // adjust address offset: + //std::cout << "B "<< this->name() <<": " << trans.get_address() << " -" << offset; + trans.set_address(trans.get_address()-offset); + //std::cout << " = " << trans.get_address() << std::endl; + i_socket->b_transport(trans, delay); + } + + //Backward Interface + tlm::tlm_sync_enum nb_transport_bw(tlm_generic_payload &trans, tlm_phase &phase, sc_time &delay) + { + //trans.set_address(trans.get_address()+offset); + return t_socket->nb_transport_bw(trans,phase,delay); + } + +}; + string pathOfFile(string file) { return file.substr(0, file.find_last_of('/')); @@ -97,21 +151,44 @@ int sc_main(int argc, char **argv) // Instantiate gem5: Gem5SimControlDRAMsys sim_control(gem5ConfigFile); -#if 1 //If only one gem5 port is used - Gem5SystemC::Gem5SlaveTransactor transactor("transactor", "transactor"); +#define CHOICE1 +//#define CHOICE2 +//#define CHOICE3 +#ifdef CHOICE1 //If only one gem5 port is used + Gem5SystemC::Gem5SlaveTransactor transactor("transactor", "transactor"); transactor.socket.bind(dramSys.tSocket); transactor.sim_control.bind(sim_control); -#else // If for example two gem5 ports are used: +#endif + +#ifdef CHOICE2 + // If there are two ports Gem5SystemC::Gem5SlaveTransactor transactor1("transactor1", "transactor1"); Gem5SystemC::Gem5SlaveTransactor transactor2("transactor2", "transactor2"); - transactor1.socket.bind(dramSys.tSocket); transactor2.socket.bind(dramSys.tSocket); transactor1.sim_control.bind(sim_control); transactor2.sim_control.bind(sim_control); #endif +#ifdef CHOICE3 + // If for example two gem5 ports are used (NVM and DRAM) with + // crazy address offsets: + Gem5SystemC::Gem5SlaveTransactor dramInterface("transactor1", "transactor1"); + Gem5SystemC::Gem5SlaveTransactor nvmInterface("transactor2", "transactor2"); + + AddressOffset nvmOffset("nvmOffset",0); + AddressOffset dramOffset("dramOffset", (2147483648-67108863));//+67108863); + + dramInterface.socket.bind(dramOffset.t_socket); + dramOffset.i_socket.bind(dramSys.tSocket); // ID0 + nvmInterface.socket.bind(nvmOffset.t_socket); + nvmOffset.i_socket.bind(dramSys.tSocket); + + dramInterface.sim_control.bind(sim_control); + nvmInterface.sim_control.bind(sim_control); +#endif + SC_REPORT_INFO("sc_main", "Start of Simulation"); sc_core::sc_set_stop_mode(SC_STOP_FINISH_DELTA); From 3a1b3cf08a2122d12e0afa31895dcc5b697e49fb Mon Sep 17 00:00:00 2001 From: Matthias Jung Date: Wed, 19 Jul 2017 13:01:05 +0300 Subject: [PATCH 5/5] New progressbar which is more smoth --- DRAMSys/simulator/src/common/Utils.h | 27 +++++++++++++++++++++++---- 1 file changed, 23 insertions(+), 4 deletions(-) diff --git a/DRAMSys/simulator/src/common/Utils.h b/DRAMSys/simulator/src/common/Utils.h index 98212eda..9d97e8dc 100644 --- a/DRAMSys/simulator/src/common/Utils.h +++ b/DRAMSys/simulator/src/common/Utils.h @@ -101,12 +101,31 @@ static inline void loadbar(unsigned int x, unsigned int n, unsigned int w = 50, float ratio = x / (float) n; unsigned int c = (ratio * w); - std::cout << std::setw(3) << round(ratio * 100) << "% ["; + float rest = (ratio * w) - c; + std::cout << std::setw(3) << round(ratio * 100) << "% |"; for (unsigned int x = 0; x < c; x++) - std::cout << "="; - for (unsigned int x = c; x < w; x++) + std::cout << "█"; + + if(rest > 0 && rest < 0.125) std::cout << " "; - std::cout << "]\r" << std::flush; + if(rest >= 0.125 && rest < 2*0.125) + std::cout << "▏"; + if(rest >= 2*0.125 && rest < 3*0.125) + std::cout << "▎"; + if(rest >= 3*0.125 && rest < 4*0.125) + std::cout << "▍"; + if(rest >= 4*0.125 && rest < 5*0.125) + std::cout << "▌"; + if(rest >= 5*0.125 && rest < 6*0.125) + std::cout << "▋"; + if(rest >= 6*0.125 && rest < 7*0.125) + std::cout << "▊"; + if(rest >= 7*0.125 && rest < 8*0.125) + std::cout << "▉"; + + for (unsigned int x = c; x < (w-1); x++) + std::cout << " "; + std::cout << "|\r" << std::flush; } //TODO : Move to debug manager