Included CheckerDDR3.

This commit is contained in:
Lukas Steiner (2)
2019-06-25 13:37:49 +02:00
parent 70b9ec8517
commit 4c4119803e
8 changed files with 639 additions and 25 deletions

View File

@@ -147,7 +147,8 @@ SOURCES += \
src/simulation/DramDDR3.cpp \
src/simulation/DramDDR4.cpp \
src/simulation/DramRecordable.cpp \
src/simulation/DramWideIO.cpp
src/simulation/DramWideIO.cpp \
src/controller/core/scheduling/checker/CheckerDDR3.cpp
HEADERS += \
src/common/third_party/tinyxml2/tinyxml2.h \
@@ -228,7 +229,8 @@ HEADERS += \
src/simulation/DramDDR3.h \
src/simulation/DramDDR4.h \
src/simulation/DramRecordable.h \
src/simulation/DramWideIO.h
src/simulation/DramWideIO.h \
src/controller/core/scheduling/checker/CheckerDDR3.h
#src/common/third_party/json/include/nlohmann/json.hpp \
thermalsim = $$(THERMALSIM)

View File

@@ -87,16 +87,6 @@ ControllerCore::ControllerCore(sc_module_name /*name*/,
if (config.RowGranularRef) {
refreshManager = new RGR("RGR", *this);
// TODO: How to use asserts with new memspec?
/*
assert(config.getTrasb() <= config.memSpec->tRAS);
assert(config.getTrasb() >= config.memSpec->tRCD);
assert(config.getTrrdb_L() <= config.memSpec->tRRD_L);
assert(config.getTrrdb_S() <= config.memSpec->tRRD_S);
assert(config.getTrpb() <= config.memSpec->tRP);
assert(config.getTrcb() <= config.memSpec->tRC);
assert(config.getTfawb() <= config.memSpec->tNAW);
*/
} else {
if (config.BankwiseLogic) {
refreshManager = new RefreshManagerBankwise("refManagerBw", *this);

View File

@@ -47,10 +47,6 @@ using namespace std;
string Configuration::memspecUri = "";
string Configuration::mcconfigUri = "";
Configuration::Configuration()
{
}
bool string2bool(string s)
{
if (s.compare("0") == 0) {

View File

@@ -160,7 +160,7 @@ struct Configuration
std::string getPathToResources();
private:
Configuration();
Configuration() {}
unsigned int powerDownTimeoutInClk = 3;
};

View File

@@ -143,20 +143,16 @@ void ConfigurationLoader::loadMemSpec(Configuration &config,
string memoryType = queryStringParameter(memspec, "memoryType");
if (memoryType == "DDR4") {
Configuration::getInstance().memSpec =
new MemSpecDDR4;
Configuration::getInstance().memSpec = new MemSpecDDR4;
loadDDR4(config, memspec);
} else if (memoryType == "DDR3") {
Configuration::getInstance().memSpec =
new MemSpecDDR3;
Configuration::getInstance().memSpec = new MemSpecDDR3;
loadDDR3(config, memspec);
} else if (memoryType == "LPDDR4") {
Configuration::getInstance().memSpec =
new MemSpecLPDDR4;
Configuration::getInstance().memSpec = new MemSpecLPDDR4;
loadLPDDR4(config, memspec);
} else if (memoryType == "WIDEIO_SDR") {
Configuration::getInstance().memSpec =
new MemSpecWideIO;
Configuration::getInstance().memSpec = new MemSpecWideIO;
loadWideIO(config, memspec);
} else {
reportFatal("ConfigurationLoader", "Unsupported DRAM type");

View File

@@ -162,6 +162,8 @@ struct MemSpec
{
return tWTR_L;
}
virtual ~MemSpec() {}
};
struct MemSpecDDR3 : public MemSpec

View File

@@ -0,0 +1,569 @@
#include "CheckerDDR3.h"
#include <iostream>
#include <algorithm>
#include <set>
#include <string>
#include "CheckerDDR3.h"
#include "../../timingCalculations.h"
#include "../../../../common/DebugManager.h"
#include "../../../Command.h"
#include "../../../../common/Utils.h"
using namespace std;
void CheckerDDR3::delayToSatisfyConstraints(ScheduledCommand &command) const
{
ScheduledCommand lastCommandOnBank = state.getLastScheduledCommand(command.getBank());
Command LastCmd = lastCommandOnBank.getCommand();
Command NextCmd = command.getCommand();
if (NextCmd == Command::Activate)
{
if (lastCommandOnBank.isValidCommand())
{
switch (LastCmd)
{
case Command::Precharge:
case Command::PrechargeAll:
command.establishMinDistanceFromStart(lastCommandOnBank.getStart(),
memSpec->tRP);
break;
case Command::ReadA:
command.establishMinDistanceFromStart(lastCommandOnBank.getStart(),
memSpec->tRTP + memSpec->tRP);
break;
case Command::WriteA:
command.establishMinDistanceFromStart(lastCommandOnBank.getStart(),
memSpec->tWL + getWriteAccessTime()
+ memSpec->tWR + memSpec->tRP);
break;
case Command::PDNPX:
case Command::PDNAX:
command.establishMinDistanceFromStart(lastCommandOnBank.getStart(),
memSpec->tXP);
break;
case Command::SREFX:
command.establishMinDistanceFromStart(lastCommandOnBank.getStart(),
memSpec->tXS);
break;
case Command::AutoRefresh:
command.establishMinDistanceFromStart(lastCommandOnBank.getStart(),
memSpec->tRFC);
break;
default:
reportFatal("Checker DDR3",
"Activate can not follow " + commandToString(LastCmd));
}
}
delay_to_satisfy_activateToActivate_sameBank(command);
while (!(state.bus.isFree(command.getStart()) &&
satsfies_activateToActivate_differentBank(command) && satisfies_nActivateWindow(command)))
{
command.delayStart(memSpec->clk);
}
}
else if (NextCmd == Command::Read || NextCmd == Command::ReadA)
{
delayToSatisfyDLL(command);
if (lastCommandOnBank.isValidCommand())
{
switch (LastCmd)
{
case Command::Activate:
command.establishMinDistanceFromStart(lastCommandOnBank.getStart(),
memSpec->tRCD);
break;
case Command::Read:
command.establishMinDistanceFromStart(lastCommandOnBank.getStart(),
CasToCas(lastCommandOnBank, command));
break;
case Command::Write:
command.establishMinDistanceFromStart(lastCommandOnBank.getStart(),
writeToRead(lastCommandOnBank, command));
break;
case Command::PDNPX:
case Command::PDNAX:
command.establishMinDistanceFromStart(lastCommandOnBank.getStart(),
memSpec->tXP);
break;
default:
reportFatal("Checker DDR3",
"Read can not follow " + commandToString(LastCmd) + "First: Activate!");
}
}
while (!state.bus.isFree(command.getStart()) || collidesOnDataStrobe_RD(command))
command.delayStart(memSpec->clk);
}
else if (NextCmd == Command::Write || NextCmd == Command::WriteA)
{
if (lastCommandOnBank.isValidCommand())
{
switch (LastCmd)
{
case Command::Activate:
command.establishMinDistanceFromStart(lastCommandOnBank.getStart(),
memSpec->tRCD);
break;
case Command::Read:
command.establishMinDistanceFromStart(lastCommandOnBank.getStart(),
readToWrite(lastCommandOnBank, command));
break;
case Command::Write:
command.establishMinDistanceFromStart(lastCommandOnBank.getStart(),
CasToCas(lastCommandOnBank, command));
break;
case Command::PDNPX:
case Command::PDNAX:
command.establishMinDistanceFromStart(lastCommandOnBank.getStart(),
memSpec->tXP);
break;
default:
reportFatal("Checker DDR3", "Write can not follow " + commandToString(LastCmd));
}
}
while (!state.bus.isFree(command.getStart()) || collidesOnDataStrobe_WR(command))
command.delayStart(memSpec->clk);
}
else if (NextCmd == Command::Precharge)
{
if (lastCommandOnBank.isValidCommand())
{
switch (LastCmd)
{
case Command::Precharge:
command.establishMinDistanceFromStart(lastCommandOnBank.getStart(),
memSpec->tRP);
break;
case Command::Activate:
command.establishMinDistanceFromStart(lastCommandOnBank.getStart(),
memSpec->tRCD);
break;
case Command::Read:
command.establishMinDistanceFromStart(lastCommandOnBank.getStart(),
memSpec->tRTP);
break;
case Command::Write:
command.establishMinDistanceFromStart(lastCommandOnBank.getStart(),
memSpec->tWL + memSpec->tWR
+ getWriteAccessTime());
break;
case Command::PDNAX:
command.establishMinDistanceFromStart(lastCommandOnBank.getStart(),
memSpec->tXP);
break;
default:
reportFatal("Checker DDR3",
"Precharge can not follow " + commandToString(LastCmd));
}
}
ScheduledCommand lastActivate = state.getLastCommand(Command::Activate, command.getBank());
if (lastActivate.isValidCommand())
command.establishMinDistanceFromStart(lastActivate.getStart(),
memSpec->tRAS);
state.bus.moveCommandToNextFreeSlot(command);
}
else if (NextCmd == Command::PrechargeAll)
{
for (unsigned int bank = 0; bank < memSpec->NumberOfBanks; bank++)
{
ScheduledCommand lastCommand = state.getLastScheduledCommand(Bank(bank));
if (lastCommand.isValidCommand())
{
switch (lastCommand.getCommand())
{
case Command::Precharge:
command.establishMinDistanceFromStart(lastCommand.getStart(),
memSpec->tRP);
break;
case Command::Activate:
command.establishMinDistanceFromStart(lastCommand.getStart(),
memSpec->tRCD);
break;
case Command::Read:
command.establishMinDistanceFromStart(lastCommand.getStart(),
memSpec->tRTP);
break;
case Command::Write:
command.establishMinDistanceFromStart(lastCommand.getStart(),
memSpec->tWL + getWriteAccessTime()
+ memSpec->tWR);
break;
case Command::WriteA:
command.establishMinDistanceFromStart(lastCommand.getStart(),
memSpec->tWL + getWriteAccessTime()
+ memSpec->tWR + memSpec->tRP);
break;
case Command::ReadA:
command.establishMinDistanceFromStart(lastCommand.getStart(),
memSpec->tRTP + memSpec->tRP);
break;
case Command::PDNAX:
case Command::PDNPX:
command.establishMinDistanceFromStart(lastCommand.getStart(),
memSpec->tXP);
break;
case Command::SREFX:
command.establishMinDistanceFromStart(lastCommand.getStart(),
memSpec->tXS);
break;
case Command::AutoRefresh:
command.establishMinDistanceFromStart(lastCommand.getStart(),
memSpec->tRFC);
break;
default:
reportFatal("Checker_DDR3",
"Precharge All can not follow " + commandToString(LastCmd));
}
}
}
ScheduledCommand lastActivate = state.getLastCommand(Command::Activate, command.getBank());
if (lastActivate.isValidCommand())
command.establishMinDistanceFromStart(lastActivate.getStart(),
memSpec->tRAS);
state.bus.moveCommandToNextFreeSlot(command);
}
else if (NextCmd == Command::PDNA || NextCmd == Command::PDNP || NextCmd == Command::SREF )
{
if (lastCommandOnBank.isValidCommand())
{
switch (LastCmd)
{
case Command::Precharge:
case Command::PrechargeAll:
command.establishMinDistanceFromStart(lastCommandOnBank.getStart(),
memSpec->tRP);
break;
case Command::Read:
case Command::ReadA:
command.establishMinDistanceFromStart(lastCommandOnBank.getStart(),
memSpec->tRL + getReadAccessTime()
+ memSpec->clk);
break;
case Command::Write:
command.establishMinDistanceFromStart(lastCommandOnBank.getStart(),
memSpec->tWL + getWriteAccessTime()
+ memSpec->tWR);
break;
case Command::WriteA:
command.establishMinDistanceFromStart(lastCommandOnBank.getStart(),
memSpec->tWL + getWriteAccessTime()
+ memSpec->tWR + memSpec->clk);
break;
case Command::AutoRefresh:
command.establishMinDistanceFromStart(lastCommandOnBank.getStart(),
memSpec->tRFC);
break;
case Command::PDNAX:
case Command::PDNPX:
command.establishMinDistanceFromStart(lastCommandOnBank.getStart(),
memSpec->tXP);
break;
case Command::SREFX:
command.establishMinDistanceFromStart(lastCommandOnBank.getStart(),
memSpec->tXS);
break;
default:
reportFatal("Checker DDR3", commandToString(NextCmd) + " can not follow "
+ commandToString(LastCmd) + ".First: Precharge!");
}
}
state.bus.moveCommandToNextFreeSlot(command);
}
else if (NextCmd == Command::PDNAX)
{
// Leaving Precharge Power Down
command.establishMinDistanceFromStart(state.getLastCommand(Command::PDNA,
command.getBank()).getStart(), memSpec->tCKE);
state.bus.moveCommandToNextFreeSlot(command);
}
else if (NextCmd == Command::PDNPX)
{
// Leaving Precharge Power Down
command.establishMinDistanceFromStart(state.getLastCommand(Command::PDNP,
command.getBank()).getStart(), memSpec->tCKE);
state.bus.moveCommandToNextFreeSlot(command);
}
else if (NextCmd == Command::SREFX)
{
// Leaving Self Refresh
command.establishMinDistanceFromStart(state.getLastCommand(Command::SREF,
command.getBank()).getStart(), memSpec->tCKESR);
state.bus.moveCommandToNextFreeSlot(command);
}
else if (NextCmd == Command::AutoRefresh)
{
if (config.BankwiseLogic) {
if (lastCommandOnBank.isValidCommand())
{
switch (LastCmd)
{
case Command::Precharge:
case Command::PrechargeAll:
command.establishMinDistanceFromStart(lastCommandOnBank.getStart(),
memSpec->tRP);
break;
case Command::ReadA:
command.establishMinDistanceFromStart(lastCommandOnBank.getStart(),
memSpec->tRTP + memSpec->tRP);
break;
case Command::WriteA:
command.establishMinDistanceFromStart(lastCommandOnBank.getStart(),
memSpec->tWL + getWriteAccessTime()
+ memSpec->tWR + memSpec->tRP);
break;
case Command::AutoRefresh:
command.establishMinDistanceFromStart(lastCommandOnBank.getStart(),
memSpec->tRFC);
break;
case Command::PDNPX:
case Command::PDNAX:
command.establishMinDistanceFromStart(lastCommandOnBank.getStart(),
memSpec->tXP);
break;
case Command::SREFX:
command.establishMinDistanceFromStart(lastCommandOnBank.getStart(),
memSpec->tXS);
break;
default:
reportFatal("Checker DDR3",
"Refresh can not follow " + commandToString(LastCmd));
}
}
}
else
{
for (unsigned int bank = 0; bank < memSpec->NumberOfBanks; bank++)
{
ScheduledCommand lastCommand = state.getLastScheduledCommand(Bank(bank));
if (lastCommand.isValidCommand())
{
switch (lastCommand.getCommand())
{
case Command::Precharge:
case Command::PrechargeAll:
command.establishMinDistanceFromStart(lastCommand.getStart(),
memSpec->tRP);
break;
case Command::Activate:
command.establishMinDistanceFromStart(lastCommand.getStart(),
memSpec->tRCD);
break;
case Command::ReadA:
command.establishMinDistanceFromStart(lastCommand.getStart(),
memSpec->tRTP + memSpec->tRP);
break;
case Command::WriteA:
command.establishMinDistanceFromStart(lastCommand.getStart(),
memSpec->tWL + getWriteAccessTime()
+ memSpec->tWR + memSpec->tRP);
break;
case Command::AutoRefresh:
command.establishMinDistanceFromStart(lastCommand.getStart(),
memSpec->tRFC);
break;
case Command::PDNPX:
case Command::PDNAX:
command.establishMinDistanceFromStart(lastCommand.getStart(),
memSpec->tXP);
break;
case Command::SREFX:
command.establishMinDistanceFromStart(lastCommand.getStart(),
memSpec->tXS);
break;
default:
reportFatal("Checker DDR3",
"Refresh can not follow " + commandToString(LastCmd));
}
}
}
}
state.bus.moveCommandToNextFreeSlot(command);
}
}
/*
* ActivateChecker
*/
void CheckerDDR3::delay_to_satisfy_activateToActivate_sameBank(ScheduledCommand &command) const
{
ScheduledCommand lastActivateOnBank = state.getLastCommand(Command::Activate, command.getBank());
if (lastActivateOnBank.isValidCommand())
command.establishMinDistanceFromStart(lastActivateOnBank.getStart(), memSpec->tRC);
}
bool CheckerDDR3::satsfies_activateToActivate_differentBank(ScheduledCommand &command) const
{
for (auto act : state.lastActivates)
{
sc_time time = act.first;
if ((time < command.getStart() && command.getStart() - time < memSpec->tRRD)
|| (command.getStart() <= time && time - command.getStart() < memSpec->tRRD))
return false;
}
return true;
}
bool CheckerDDR3::satisfies_nActivateWindow(ScheduledCommand &command) const
{
/*
* there may be activates scheduled in the future, so emplace
* command in a copied set (not necessarily the last in time),
* and check if the n-act constraint holds for the whole set.
*/
if (state.lastActivates.size() >= memSpec->nActivate)
{
std::map<sc_time, ScheduledCommand> lastActivates = state.lastActivates;
lastActivates.emplace(command.getStart(), command);
auto upper = lastActivates.begin();
std::advance(upper, memSpec->nActivate);
auto lower = lastActivates.begin();
while (upper != lastActivates.end())
{
if (upper->first - lower->first < memSpec->tNAW)
return false;
upper++;
lower++;
}
}
return true;
}
/*
* Read-Checker
*/
bool CheckerDDR3::collidesOnDataStrobe_RD(ScheduledCommand &read) const
{
for (ScheduledCommand &strobeCommand : state.lastDataStrobeCommands)
{
if (collidesWithStrobeCommand_RD(read, strobeCommand))
return true;
}
return false;
}
bool CheckerDDR3::collidesWithStrobeCommand_RD(ScheduledCommand &read,
ScheduledCommand &strobeCommand) const
{
if (strobeCommand.getCommand() == Command::Read || strobeCommand.getCommand() == Command::ReadA)
{
return getDistance(read.getStart(),
strobeCommand.getStart()) < CasToCas(strobeCommand, read);
}
else if (strobeCommand.getCommand() == Command::Write || strobeCommand.getCommand() == Command::WriteA)
{
if (strobeCommand.getStart() >= read.getStart())
return getDistance(read.getStart(),
strobeCommand.getStart()) < readToWrite(read, strobeCommand);
else
return getDistance(strobeCommand.getStart(),
read.getStart()) < writeToRead(strobeCommand, read);
} else {
reportFatal("Checker DDR3",
"Invalid strobeCommand in data strobe commands " + commandToString(
strobeCommand.getCommand()));
return true;
}
return false;
}
void CheckerDDR3::delayToSatisfyDLL(ScheduledCommand &read) const
{
ScheduledCommand lastSREFX = state.getLastCommand(Command::SREFX, read.getBank());
if (lastSREFX.isValidCommand())
read.establishMinDistanceFromStart(lastSREFX.getStart(), memSpec->tXSDLL);
}
sc_time CheckerDDR3::writeToRead(ScheduledCommand &write, ScheduledCommand &read)
{
sc_assert(read.getCommand() == Command::Read || read.getCommand() == Command::ReadA);
sc_assert(write.getCommand() == Command::Write || write.getCommand() == Command::WriteA);
if (write.getBankGroup() == read.getBankGroup())
{
return memSpec->tWL + getWriteAccessTime() + memSpec->tWTR;
}
}
/* CAS-CAS */
sc_time CheckerDDR3::CasToCas(ScheduledCommand &firstCAS, ScheduledCommand &secondCAS)
{
if (firstCAS.getCommand() == Command::Read || firstCAS.getCommand() == Command::ReadA)
{
if (secondCAS.getCommand() == Command::Read || secondCAS.getCommand() == Command::ReadA)
{
if (firstCAS.getBankGroup() == secondCAS.getBankGroup())
return std::max(memSpec->tCCD, getReadAccessTime());
}
}
else if (firstCAS.getCommand() == Command::Write || firstCAS.getCommand() == Command::WriteA)
{
if (secondCAS.getCommand() == Command::Write || secondCAS.getCommand() == Command::WriteA)
{
if (firstCAS.getBankGroup() == secondCAS.getBankGroup())
return std::max(memSpec->tCCD, getWriteAccessTime());
}
}
}
/*
* Write-Checker
*/
bool CheckerDDR3::collidesOnDataStrobe_WR(ScheduledCommand &write) const
{
for (ScheduledCommand &strobeCommand : state.lastDataStrobeCommands)
{
if (collidesWithStrobeCommand_WR(write, strobeCommand))
return true;
}
return false;
}
bool CheckerDDR3::collidesWithStrobeCommand_WR(ScheduledCommand &write,
ScheduledCommand &strobeCommand) const
{
if (strobeCommand.getCommand() == Command::Write || strobeCommand.getCommand() == Command::WriteA)
{
// TODO: Cast from sc_time to bool?
return getDistance(write.getStart(),
strobeCommand.getStart()) < CasToCas(strobeCommand, write);
}
else if (strobeCommand.getCommand() == Command::Read || strobeCommand.getCommand() == Command::ReadA)
{
if (strobeCommand.getStart() >= write.getStart())
return getDistance(write.getStart(),
strobeCommand.getStart()) < writeToRead(write, strobeCommand);
else
return getDistance(strobeCommand.getStart(),
write.getStart()) < readToWrite(strobeCommand, write);
}
else
{
reportFatal("CheckerDDR3", "Invalid strobeCommand in data strobe commands "
+ commandToString(strobeCommand.getCommand()));
return true;
}
}
sc_time CheckerDDR3::readToWrite(ScheduledCommand &read, ScheduledCommand &write)
{
sc_assert(read.getCommand() == Command::Read
|| read.getCommand() == Command::ReadA);
sc_assert(write.getCommand() == Command::Write
|| write.getCommand() == Command::WriteA);
return memSpec->tRL + getReadAccessTime() - memSpec->tWL + memSpec->clk * 2;
}

View File

@@ -0,0 +1,59 @@
#ifndef CHECKERDDR3_H
#define CHECKERDDR3_H
#include "ICommandChecker.h"
#include "../../configuration/Configuration.h"
#include "../../../ControllerState.h"
//Activate
class CheckerDDR3: public ICommandChecker
{
public:
CheckerDDR3(const Configuration &config,
ControllerState &state) : config(config), state(state)
{
memSpec = dynamic_cast<MemSpecDDR3 *>(Configuration::getInstance().memSpec);
if (memSpec == nullptr)
SC_REPORT_FATAL("CheckerDDR3", "Wrong MemSpec chosen.");
}
virtual ~CheckerDDR3() {}
virtual void delayToSatisfyConstraints(ScheduledCommand &command) const
override;
private:
static MemSpecDDR3 *memSpec;
//Activate
void delay_to_satisfy_activateToActivate_sameBank(ScheduledCommand &command) const;
bool satsfies_activateToActivate_differentBank(ScheduledCommand &command) const;
bool satisfies_nActivateWindow(ScheduledCommand &command) const;
//PowerDown
sc_time getTimeConstraintToEnterPowerDown(Command lastCmd, Command pdnCmd) const;
//used for Read
void delayToSatisfyDLL(ScheduledCommand &read) const;
bool collidesOnDataStrobe_RD(ScheduledCommand &read) const;
bool collidesWithStrobeCommand_RD(ScheduledCommand &read,
ScheduledCommand &strobeCommand) const;
//Write
bool collidesOnDataStrobe_WR(ScheduledCommand &write) const;
bool collidesWithStrobeCommand_WR(ScheduledCommand &write,
ScheduledCommand &strobeCommand) const;
//handles WR->RD
static sc_time writeToRead(ScheduledCommand &write, ScheduledCommand &read);
//RD->WR
static sc_time readToWrite(ScheduledCommand &read, ScheduledCommand &write);
//CasToCas Commands (WR->WR)(RD->RD)
static sc_time CasToCas(ScheduledCommand &firstCAS, ScheduledCommand &secondCAS);
const Configuration &config;
ControllerState &state;//TODO make const
};
#endif // CHECKERDDR3_H