Implemented closed page policy. Fixed bug in trace analyzer tests.
This commit is contained in:
@@ -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;
|
||||
}
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -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)
|
||||
{
|
||||
|
||||
@@ -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
|
||||
|
||||
|
||||
Reference in New Issue
Block a user