Merge branch 'master' into SMS_fixbug
* master: New progressbar which is more smoth Added an address offset to the gem5 setup Read before write in miss scenarios for FR_FCFS_RP Changed FR_FCFS_RP to C++11 style Changed FR_FCFS_RP Scheduler
This commit is contained in:
@@ -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<AddressOffset> t_socket;
|
||||
tlm_utils::simple_initiator_socket<AddressOffset> 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);
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
<mcconfig>
|
||||
<BankwiseLogic value="0"/>
|
||||
<OpenPagePolicy value="1" />
|
||||
<MaxNrOfTransactions value="8" />
|
||||
<MaxNrOfTransactions value="16" />
|
||||
<Scheduler value="FR_FCFS_RP" />
|
||||
<Capsize value="5" />
|
||||
<!-- 4 Modes: NoPowerDown, Staggered, TimeoutPDN, TimeoutSREF -->
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -57,9 +57,9 @@ public:
|
||||
|
||||
protected:
|
||||
std::map<Bank, std::deque<gp*>> buffer;
|
||||
std::deque<gp*>::iterator FindRowHit(Bank bank);
|
||||
|
||||
private:
|
||||
std::deque<gp*>::iterator FindRowHit(Bank bank);
|
||||
|
||||
};
|
||||
|
||||
|
||||
@@ -40,72 +40,115 @@
|
||||
|
||||
std::pair<Command, gp*> 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, tlm::tlm_generic_payload*>(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<gp*>::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<Command, gp*>(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<Command, gp*>(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<Command, gp*>(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<Command, gp*>(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<Command, gp*>(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<Command, gp*>(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<gp*>::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<gp*>::iterator ext)
|
||||
{
|
||||
deque<gp*> &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);
|
||||
}
|
||||
|
||||
@@ -48,7 +48,8 @@ public:
|
||||
|
||||
private:
|
||||
|
||||
std::deque<gp*>::iterator FindRowHit_RP(Bank bank);
|
||||
bool hazardDetection(Bank bank, std::deque<gp*>::iterator ext);
|
||||
void printDebugMessage(std::string message);
|
||||
};
|
||||
|
||||
#endif // FR_FCFS_READ_PRIORITY_H
|
||||
|
||||
Reference in New Issue
Block a user