Implemented closed page policy. Fixed bug in trace analyzer tests.

This commit is contained in:
Lukas Steiner (2)
2019-09-11 16:02:36 +02:00
parent 7fd5f05d3e
commit 62841a3590
7 changed files with 161 additions and 66 deletions

View File

@@ -37,53 +37,6 @@
BankMachine::BankMachine(SchedulerIF *scheduler, CheckerIF *checker, Bank bank)
: scheduler(scheduler), checker(checker), bank(bank) {}
sc_time BankMachine::startBankMachine()
{
if (currentPayload == nullptr)
{
currentPayload = scheduler->getNextRequest(bank, this);
if (currentPayload == nullptr)
return SC_ZERO_TIME;
}
sc_time delay;
DramExtension extension = DramExtension::getExtension(currentPayload);
if (currentState == BmState::Precharged) // row miss
{
delay = checker->delayToSatisfyConstraints(Command::ACT, bank);
nextCommand = Command::ACT;
nextRow = extension.getRow();
timeToSchedule = sc_time_stamp() + delay;
}
else if (currentState == BmState::Activated)
{
if (extension.getRow() == currentRow) // row hit
{
if (currentPayload->get_command() == TLM_READ_COMMAND)
{
delay = checker->delayToSatisfyConstraints(Command::RD, bank);
nextCommand = Command::RD;
timeToSchedule = sc_time_stamp() + delay;
}
else if (currentPayload->get_command() == TLM_WRITE_COMMAND)
{
delay = checker->delayToSatisfyConstraints(Command::WR, bank);
nextCommand = Command::WR;
timeToSchedule = sc_time_stamp() + delay;
}
else
SC_REPORT_FATAL("BankMachine", "Wrong TLM command");
}
else // row miss
{
delay = checker->delayToSatisfyConstraints(Command::PRE, bank);
nextCommand = Command::PRE;
nextRow = extension.getRow();
timeToSchedule = sc_time_stamp() + delay;
}
}
return delay;
}
std::pair<Command, tlm_generic_payload *> BankMachine::getNextCommand()
{
if (sc_time_stamp() == timeToSchedule)
@@ -103,6 +56,11 @@ void BankMachine::updateState(Command command)
currentState = BmState::Precharged;
else if (command == Command::RD || command == Command::WR)
currentPayload = nullptr;
else if (command == Command::RDA || command == Command::WRA)
{
currentState = BmState::Precharged;
currentPayload = nullptr;
}
else
SC_REPORT_FATAL("BankMachine", "Unknown phase");
}
@@ -127,3 +85,97 @@ BmState BankMachine::getState()
{
return currentState;
}
BankMachineOpen::BankMachineOpen(SchedulerIF *scheduler, CheckerIF *checker, Bank bank)
: BankMachine(scheduler, checker, bank) {}
sc_time BankMachineOpen::startBankMachine()
{
if (currentPayload == nullptr)
{
currentPayload = scheduler->getNextRequest(bank, this);
if (currentPayload == nullptr)
return SC_ZERO_TIME;
}
sc_time delay;
DramExtension extension = DramExtension::getExtension(currentPayload);
if (currentState == BmState::Precharged) // row miss
{
delay = checker->delayToSatisfyConstraints(Command::ACT, bank);
nextCommand = Command::ACT;
nextRow = extension.getRow();
}
else if (currentState == BmState::Activated)
{
if (extension.getRow() == currentRow) // row hit
{
if (currentPayload->get_command() == TLM_READ_COMMAND)
{
delay = checker->delayToSatisfyConstraints(Command::RD, bank);
nextCommand = Command::RD;
}
else if (currentPayload->get_command() == TLM_WRITE_COMMAND)
{
delay = checker->delayToSatisfyConstraints(Command::WR, bank);
nextCommand = Command::WR;
}
else
SC_REPORT_FATAL("BankMachine", "Wrong TLM command");
}
else // row miss
{
delay = checker->delayToSatisfyConstraints(Command::PRE, bank);
nextCommand = Command::PRE;
nextRow = extension.getRow();
}
}
timeToSchedule = sc_time_stamp() + delay;
return delay;
}
BankMachineClosed::BankMachineClosed(SchedulerIF *scheduler, CheckerIF *checker, Bank bank)
: BankMachine(scheduler, checker, bank) {}
sc_time BankMachineClosed::startBankMachine()
{
if (currentPayload == nullptr)
{
currentPayload = scheduler->getNextRequest(bank, this);
if (currentPayload == nullptr)
return SC_ZERO_TIME;
}
sc_time delay;
DramExtension extension = DramExtension::getExtension(currentPayload);
if (currentState == BmState::Precharged) // row miss
{
delay = checker->delayToSatisfyConstraints(Command::ACT, bank);
nextCommand = Command::ACT;
nextRow = extension.getRow();
}
else if (currentState == BmState::Activated)
{
if (extension.getRow() == currentRow) // row hit
{
if (currentPayload->get_command() == TLM_READ_COMMAND)
{
delay = checker->delayToSatisfyConstraints(Command::RDA, bank);
nextCommand = Command::RDA;
}
else if (currentPayload->get_command() == TLM_WRITE_COMMAND)
{
delay = checker->delayToSatisfyConstraints(Command::WRA, bank);
nextCommand = Command::WRA;
}
else
SC_REPORT_FATAL("BankMachine", "Wrong TLM command");
}
else // row miss
{
delay = checker->delayToSatisfyConstraints(Command::PRE, bank);
nextCommand = Command::PRE;
nextRow = extension.getRow();
}
}
timeToSchedule = sc_time_stamp() + delay;
return delay;
}

View File

@@ -58,8 +58,8 @@ enum class BmState
class BankMachine
{
public:
BankMachine(SchedulerIF *, CheckerIF*, Bank);
sc_time startBankMachine();
virtual ~BankMachine() {}
virtual sc_time startBankMachine() = 0;
std::pair<Command, tlm_generic_payload *> getNextCommand();
void updateState(Command);
bool forcePrecharge();
@@ -67,16 +67,31 @@ public:
Row getOpenRow();
BmState getState();
private:
protected:
BankMachine(SchedulerIF *, CheckerIF *, Bank);
tlm_generic_payload *currentPayload = nullptr;
BmState currentState = BmState::Precharged;
Bank bank;
Row currentRow;
Row nextRow;
Command nextCommand;
sc_time timeToSchedule = SC_ZERO_TIME;
SchedulerIF *scheduler;
CheckerIF *checker;
Command nextCommand;
Row nextRow;
BmState currentState = BmState::Precharged;
Row currentRow;
sc_time timeToSchedule = SC_ZERO_TIME;
Bank bank;
};
class BankMachineOpen final : public BankMachine
{
public:
BankMachineOpen(SchedulerIF *, CheckerIF *, Bank);
sc_time startBankMachine();
};
class BankMachineClosed final : public BankMachine
{
public:
BankMachineClosed(SchedulerIF *, CheckerIF *, Bank);
sc_time startBankMachine();
};
#endif // BANKMACHINE_H

View File

@@ -91,8 +91,16 @@ Controller::Controller(sc_module_name name) :
else
SC_REPORT_FATAL("Controller", "Selected scheduler not supported");
for (unsigned bankID = 0; bankID < Configuration::getInstance().memSpec->NumberOfBanks; bankID++)
bankMachines[Bank(bankID)] = new BankMachine(scheduler, checker, Bank(bankID));
if (config.OpenPagePolicy)
{
for (unsigned bankID = 0; bankID < config.memSpec->NumberOfBanks; bankID++)
bankMachines[Bank(bankID)] = new BankMachineOpen(scheduler, checker, Bank(bankID));
}
else
{
for (unsigned bankID = 0; bankID < config.memSpec->NumberOfBanks; bankID++)
bankMachines[Bank(bankID)] = new BankMachineClosed(scheduler, checker, Bank(bankID));
}
startBandwidthIdleCollector();
}
@@ -211,7 +219,7 @@ tlm_sync_enum Controller::nb_transport_bw(tlm_generic_payload &trans,
PRINTDEBUGMESSAGE(name(), "[bw] " + phaseNameToString(phase) + " notification in " +
delay.to_string());
if (phase == END_RD || phase == END_WR)
if (phase == END_RD || phase == END_RDA || phase == END_WR || phase == END_WRA)
{
std::pair<sc_time, tlm_generic_payload *> element((sc_time_stamp() + delay), &trans);
responseQueue.push(element);
@@ -276,8 +284,12 @@ void Controller::sendToDram(Command command, tlm_generic_payload *payload)
phase = BEGIN_PRE;
else if (command == Command::RD)
phase = BEGIN_RD;
else if (command == Command::RDA)
phase = BEGIN_RDA;
else if (command == Command::WR)
phase = BEGIN_WR;
else if (command == Command::WRA)
phase = BEGIN_WRA;
else if (command == Command::PREA)
phase = BEGIN_PREA;
else if (command == Command::REFA)

View File

@@ -60,7 +60,7 @@ void ControllerRecordable::sendToFrontend(tlm_generic_payload *payload, tlm_phas
void ControllerRecordable::sendToDram(Command command, tlm_generic_payload *payload)
{
if (command == Command::RD || command == Command::WR)
if (commandIsIn(command, {Command::RD, Command::RDA, Command::WR, Command::WRA}))
{
sc_time execTime = Configuration::getInstance().memSpec->getExecutionTime(command);
ScheduledCommand scheduledCommand(command, sc_time_stamp(), execTime, *payload);

View File

@@ -103,10 +103,18 @@ sc_time CheckerDDR3::delayToSatisfyConstraints(Command command, Bank bank)
if (lastCommand.isValidCommand())
earliestTimeToStart = std::max(earliestTimeToStart, lastCommand.getStart() + memSpec->tCCD);
lastCommand = lastScheduledByCommand[Command::RDA];
if (lastCommand.isValidCommand())
earliestTimeToStart = std::max(earliestTimeToStart, lastCommand.getStart() + memSpec->tCCD);
lastCommand = lastScheduledByCommand[Command::WR];
if (lastCommand.isValidCommand())
earliestTimeToStart = std::max(earliestTimeToStart, lastCommand.getStart() + memSpec->tWL + memSpec->tCCD + memSpec->tWTR);
lastCommand = lastScheduledByCommand[Command::WRA];
if (lastCommand.isValidCommand())
earliestTimeToStart = std::max(earliestTimeToStart, lastCommand.getStart() + memSpec->tWL + memSpec->tCCD + memSpec->tWTR);
refreshChecker->delayToSatisfyRD(bank, earliestTimeToStart);
}
else if (command == Command::WR || command == Command::WRA)
@@ -118,10 +126,18 @@ sc_time CheckerDDR3::delayToSatisfyConstraints(Command command, Bank bank)
if (lastCommand.isValidCommand())
earliestTimeToStart = std::max(earliestTimeToStart, lastCommand.getStart() + memSpec->tRL + memSpec->tCCD + 2 * memSpec->clk - memSpec->tWL);
lastCommand = lastScheduledByCommand[Command::RDA];
if (lastCommand.isValidCommand())
earliestTimeToStart = std::max(earliestTimeToStart, lastCommand.getStart() + memSpec->tRL + memSpec->tCCD + 2 * memSpec->clk - memSpec->tWL);
lastCommand = lastScheduledByCommand[Command::WR];
if (lastCommand.isValidCommand())
earliestTimeToStart = std::max(earliestTimeToStart, lastCommand.getStart() + memSpec->tCCD);
lastCommand = lastScheduledByCommand[Command::WRA];
if (lastCommand.isValidCommand())
earliestTimeToStart = std::max(earliestTimeToStart, lastCommand.getStart() + memSpec->tCCD);
refreshChecker->delayToSatisfyWR(bank, earliestTimeToStart);
}
else if (command == Command::PRE)

View File

@@ -46,7 +46,7 @@ CmdMuxStrict::selectCommand(std::vector<std::pair<Command, tlm_generic_payload *
}
for (auto it : readyCommands)
{
if (it.first == Command::RD || it.first == Command::WR)
if (commandIsIn(it.first, {Command::RD, Command::RDA, Command::WR, Command::WRA}))
{
if (DramExtension::getPayloadID(it.second) == nextPayloadID)
{

View File

@@ -331,11 +331,11 @@ def timing_constraint(FirstPhase, SecondPhase):
if (SecondPhaseName in ["PRE, PREA"]):
return dramconfig.tRTP
elif (SecondPhaseName in ["RD, RDA"]):
return max(dramconfig.tCCD_L, getReadAccessTime())
return max(dramconfig.tCCD_L, dramconfig.getReadAccessTime())
elif (SecondPhase in ["WR", "WRA"]):
return dramconfig.tRL + getReadAccessTime() - dramconfig.tWL + 2 * dramconfig.clk
return dramconfig.tRL + dramconfig.getReadAccessTime() - dramconfig.tWL + 2 * dramconfig.clk
elif (SecondPhase == "PDNA"):
return dramconfig.tRL + getReadAccessTime() + dramconfig.clk
return dramconfig.tRL + dramconfig.getReadAccessTime() + dramconfig.clk
elif (FirstPhaseName == "WR"):
if (SecondPhaseName in ["PRE, PREA", "PDNA"]):
@@ -349,11 +349,11 @@ def timing_constraint(FirstPhase, SecondPhase):
if (SecondPhaseName in ["ACT", "PREA", "REFA"]):
return dramconfig.tRTP + dramconfig.tRP
elif (SecondPhaseName in ["PDNA", "PDNP"]):
return dramconfig.tRL + getReadAccessTime() + dramconfig.clk
return dramconfig.tRL + dramconfig.getReadAccessTime() + dramconfig.clk
elif (FirstPhaseName == "WRA"):
if (SecondPhaseName in ["ACT", "PREA", "REFA"]):
return dramconfig.tWL + getWriteAccessTime() + dramconfig.tWR + dramconfig.tRP
return dramconfig.tWL + dramconfig.getWriteAccessTime() + dramconfig.tWR + dramconfig.tRP
elif (SecondPhaseName in ["PDNA", "PDNP"]):
return dramconfig.tWL + dramconfig.getWriteAccessTime() + dramconfig.tWR + dramconfig.clk