|
|
|
|
@@ -40,72 +40,100 @@
|
|
|
|
|
|
|
|
|
|
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) TODO
|
|
|
|
|
// 4. Write Miss TODO
|
|
|
|
|
|
|
|
|
|
if(DebugManager::getInstance().writeToConsole == true)
|
|
|
|
|
{
|
|
|
|
|
gp* payload = *it;
|
|
|
|
|
buffer[bank].erase(it);
|
|
|
|
|
return pair<Command, gp*>(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<Command, gp*>(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<Command, gp*>(getReadWriteCommand(*write),
|
|
|
|
|
write);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// For now return the oldest request. TODO: do read first!
|
|
|
|
|
return pair<Command, gp*>(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<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, unsigned long id)
|
|
|
|
|
{
|
|
|
|
|
deque<gp*> &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);
|
|
|
|
|
}
|
|
|
|
|
|