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); 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/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 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..57a5b7b3 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,115 @@ 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) + // 4. Write Miss + + // 1. Seach for read hit: + for(auto it = buffer[bank].begin(); it!=buffer[bank].end(); it++) { - gp* payload = *it; - buffer[bank].erase(it); - return pair(getReadWriteCommand(*payload), payload); + gp* read = *it; + + 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, it) == false) + { + buffer[bank].erase(it); + printDebugMessage("Read Hit found"); + return pair(getReadWriteCommand(*read),read); + } + } + } } - // If there is no row hit, the FR_FCFS takes always the oldest transaction - // in the buffer, i.e. the transaction in the front. - return pair(getNextCommand(buffer[bank].front()), - buffer[bank].front()); + // 2. Search for write hit: + for(auto it = buffer[bank].begin(); it!=buffer[bank].end(); it++) + { + gp* write = *it; + + 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(it); + printDebugMessage("Write Hit found"); + return pair(getReadWriteCommand(*write),write); + } + } + } + + // 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 ..."); } -// 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, std::deque::iterator ext) { - deque &queue = buffer[bank]; + gp* read = *ext; - 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++) + for(auto it = buffer[bank].begin(); it!=ext; 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_READ_COMMAND) + gp* write = *it; + 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..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,8 @@ public: private: - std::deque::iterator FindRowHit_RP(Bank bank); + bool hazardDetection(Bank bank, std::deque::iterator ext); + void printDebugMessage(std::string message); }; #endif // FR_FCFS_READ_PRIORITY_H