first ddr4 changes
This commit is contained in:
@@ -32,7 +32,7 @@
|
||||
<!--<parameter id="CL" type="uint" value="3" />-->
|
||||
<parameter id="TAW" type="uint" value="10" />
|
||||
<parameter id="RRD" type="uint" value="2" />
|
||||
<!--<parameter id="CCD" type="uint" value="1" />-->
|
||||
<parameter id="CCD" type="uint" value="1" />
|
||||
<parameter id="WTR" type="uint" value="3" />
|
||||
<parameter id="CKE" type="uint" value="3" />
|
||||
<parameter id="CKESR" type="uint" value="3" />
|
||||
|
||||
@@ -156,22 +156,6 @@ bool ControllerCore::isBusy(sc_time time, Bank bank)
|
||||
|
||||
}
|
||||
|
||||
BankGroup ControllerCore::getBankGroup(Bank bank) const
|
||||
{
|
||||
static std::map<Bank, BankGroup> bankgroups;
|
||||
if (bankgroups.size() == 0)
|
||||
{
|
||||
SC_ASSERT_(config.NumberOfBanks % config.NumberOfBankGroups == 0, "Number of banks must be a multiple of number of bankgroups");
|
||||
|
||||
for (unsigned int bank = 0; bank < config.NumberOfBanks; bank++)
|
||||
{
|
||||
unsigned int group = bank / config.NumberOfBankGroups;
|
||||
bankgroups.insert(std::pair<Bank, BankGroup>(Bank(bank), BankGroup(group)));
|
||||
}
|
||||
}
|
||||
return bankgroups.at(bank);
|
||||
}
|
||||
|
||||
const std::vector<Bank>& ControllerCore::getBanks() const
|
||||
{
|
||||
static std::vector<Bank> banks;
|
||||
|
||||
@@ -37,8 +37,8 @@ public:
|
||||
void saveState();
|
||||
void resetState();
|
||||
|
||||
BankGroup getBankGroup(Bank bank) const;
|
||||
const std::vector<Bank>& getBanks() const;
|
||||
|
||||
const std::vector<Bank>& getBanks() const;//TODO put in config?
|
||||
|
||||
void send(const CommandSchedule& schedule, tlm::tlm_generic_payload& payload) const;
|
||||
ICommandChecker& getCommandChecker(Command command);
|
||||
|
||||
@@ -68,7 +68,7 @@ void ControllerState::change(const ScheduledCommand& scheduledCommand)
|
||||
break;
|
||||
case Command::Activate:
|
||||
bankStates.openRowInRowBuffer(scheduledCommand.getBank(), scheduledCommand.getRow());
|
||||
lastActivates.emplace(scheduledCommand.getStart());
|
||||
lastActivates.emplace(scheduledCommand.getStart(), scheduledCommand.getBank());
|
||||
break;
|
||||
|
||||
case Command::Precharge:
|
||||
|
||||
@@ -44,7 +44,7 @@ public:
|
||||
std::map<Command, std::map<Bank, ScheduledCommand> > lastCommandsOnBus;
|
||||
Slots bus;
|
||||
std::list<ScheduledCommand> lastDataStrobeCommands;
|
||||
std::set<sc_time> lastActivates;
|
||||
std::map<sc_time, Bank> lastActivates;
|
||||
|
||||
private:
|
||||
Configuration* config;
|
||||
|
||||
@@ -57,7 +57,50 @@ void MemSpecLoader::loadConfig(Configuration& config, XMLElement* memspec)
|
||||
|
||||
void MemSpecLoader::loadDDR4(Configuration& config, XMLElement* memspec)
|
||||
{
|
||||
//MemSpecification
|
||||
XMLElement* architecture = memspec->FirstChildElement("memarchitecturespec");
|
||||
|
||||
config.NumberOfBanks = queryUIntParameter(architecture, "nbrOfBanks");
|
||||
config.NumberOfBankGroups = queryUIntParameter(architecture, "nbrOfBankGroups");
|
||||
config.BurstLength = queryUIntParameter(architecture, "burstLength");
|
||||
config.nActivate = 4;
|
||||
config.DataRate = queryUIntParameter(architecture, "dataRate");
|
||||
config.NumberOfRows = queryUIntParameter(architecture, "nbrOfRows");
|
||||
|
||||
//MemTimings
|
||||
XMLElement* timings = memspec->FirstChildElement("memtimingspec");
|
||||
double clkMhz = queryDoubleParameter(timings, "clkMhz");
|
||||
sc_time clk = sc_time(1 / clkMhz, SC_US);
|
||||
config.Timings.clk = clk;
|
||||
//TODO
|
||||
config.Timings.tRP = clk * queryUIntParameter(timings, "RP");
|
||||
config.Timings.tRAS = clk * queryUIntParameter(timings, "RAS");
|
||||
config.Timings.tRC = clk * queryUIntParameter(timings, "RC");
|
||||
config.Timings.tRRD_S = clk * queryUIntParameter(timings, "RRD_S");
|
||||
config.Timings.tRRD_L = clk * queryUIntParameter(timings, "RRD_L");
|
||||
config.Timings.tCCD_S = clk * queryUIntParameter(timings, "CCD_S");
|
||||
config.Timings.tCCD_L = clk * queryUIntParameter(timings, "CCD_L");
|
||||
config.Timings.tRCD = clk * queryUIntParameter(timings, "RCD");
|
||||
config.Timings.tNAW = clk * queryUIntParameter(timings, "TAW");
|
||||
config.Timings.tRL = clk * queryUIntParameter(timings, "RL");
|
||||
config.Timings.tWL = clk * queryUIntParameter(timings, "WL");
|
||||
config.Timings.tWR = clk * queryUIntParameter(timings, "WR");
|
||||
config.Timings.tWTR_S = clk * queryUIntParameter(timings, "WTR_S");
|
||||
config.Timings.tWTR_L = clk * queryUIntParameter(timings, "WTR_L");
|
||||
config.Timings.tCKESR = clk * queryUIntParameter(timings, "CKESR");
|
||||
config.Timings.tCKE = clk * queryUIntParameter(timings, "CKE");
|
||||
config.Timings.tXP = clk * queryUIntParameter(timings, "XP");
|
||||
config.Timings.tXSR = clk * queryUIntParameter(timings, "XS");
|
||||
config.Timings.tAL = clk * queryUIntParameter(timings, "AL");
|
||||
config.Timings.tRFC = clk * queryUIntParameter(timings, "RFC");
|
||||
config.Timings.tREFI = clk * queryUIntParameter(timings, "REFI");
|
||||
|
||||
config.Timings.refreshTimings.clear();
|
||||
for (unsigned int i = 0; i < config.NumberOfBanks; ++i)
|
||||
{
|
||||
config.Timings.refreshTimings.push_back(
|
||||
RefreshTiming(config.Timings.tRFC, config.Timings.tREFI));
|
||||
}
|
||||
}
|
||||
|
||||
void MemSpecLoader::loadWideIO(Configuration& config, XMLElement* memspec)
|
||||
@@ -81,13 +124,17 @@ void MemSpecLoader::loadWideIO(Configuration& config, XMLElement* memspec)
|
||||
config.Timings.tRP = clk * queryUIntParameter(timings, "RP");
|
||||
config.Timings.tRAS = clk * queryUIntParameter(timings, "RAS");
|
||||
config.Timings.tRC = clk * queryUIntParameter(timings, "RC");
|
||||
config.Timings.tRRD = clk * queryUIntParameter(timings, "RRD");
|
||||
config.Timings.tRRD_S = clk * queryUIntParameter(timings, "RRD");
|
||||
config.Timings.tRRD_L = config.Timings.tRRD_S;
|
||||
config.Timings.tCCD_S = clk * queryUIntParameter(timings, "CCD");
|
||||
config.Timings.tCCD_L = config.Timings.tCCD_S;
|
||||
config.Timings.tRCD = clk * queryUIntParameter(timings, "RCD");
|
||||
config.Timings.tNAW = clk * queryUIntParameter(timings, "TAW");
|
||||
config.Timings.tRL = clk * queryUIntParameter(timings, "RL");
|
||||
config.Timings.tWL = clk * queryUIntParameter(timings, "WL");
|
||||
config.Timings.tWR = clk * queryUIntParameter(timings, "WR");
|
||||
config.Timings.tWTR = clk * queryUIntParameter(timings, "WTR");
|
||||
config.Timings.tWTR_S = clk * queryUIntParameter(timings, "WTR");
|
||||
config.Timings.tWTR_L = config.Timings.tWTR_S;
|
||||
config.Timings.tCKESR = clk * queryUIntParameter(timings, "CKESR");
|
||||
config.Timings.tCKE = clk * queryUIntParameter(timings, "CKE");
|
||||
config.Timings.tXP = clk * queryUIntParameter(timings, "XP");
|
||||
|
||||
@@ -30,17 +30,17 @@ struct TimingConfiguration
|
||||
sc_time tRP; //precharge-time (pre -> act same bank)
|
||||
sc_time tRAS; //active-time (act -> pre same bank)
|
||||
sc_time tRC; //RAS-cycle-time (min time bw 2 succesive ACT to same bank)
|
||||
sc_time tCCD; //TODO: relevant? max(bl, tCCD)
|
||||
//sc_time tCCD_L;
|
||||
sc_time tRRD; //min time bw 2 succesive ACT to different banks (different bank group)
|
||||
//sc_time tRRD_L; //.. (same bank group)
|
||||
sc_time tCCD_S; //TODO: relevant? max(bl, tCCD)
|
||||
sc_time tCCD_L;
|
||||
sc_time tRRD_S; //min time bw 2 succesive ACT to different banks (different bank group)
|
||||
sc_time tRRD_L; //.. (same bank group)
|
||||
sc_time tRCD; //act -> read/write
|
||||
sc_time tNAW; //n activate window
|
||||
sc_time tRL; //read latency (read command start to data strobe)
|
||||
sc_time tWL; //write latency
|
||||
sc_time tWR; //write recovery (write to precharge)
|
||||
sc_time tWTR; //write to read (different bank group)
|
||||
//sc_time tWTR_L; //.. (same bank group)
|
||||
sc_time tWTR_S; //write to read (different bank group)
|
||||
sc_time tWTR_L; //.. (same bank group)
|
||||
sc_time tCKESR; //min time in sref
|
||||
sc_time tCKE; //min time in pdna or pdnp
|
||||
sc_time tXP; //min delay to row access command after pdnpx pdnax
|
||||
@@ -54,7 +54,7 @@ struct TimingConfiguration
|
||||
|
||||
//act and read/write commands remain for this timespan in history
|
||||
sc_time tActHistory(){return tNAW;}
|
||||
sc_time tDataStrobeHistory(){return tWTR;}
|
||||
sc_time tDataStrobeHistory(){return tWTR_L;}
|
||||
};
|
||||
|
||||
} /* namespace core */
|
||||
|
||||
@@ -33,7 +33,7 @@ void ActivateChecker::delayToSatisfyConstraints(ScheduledCommand& command) const
|
||||
{
|
||||
command.delayToMeetConstraint(lastCommandOnBank.getEnd(), config.Timings.tXP);
|
||||
}
|
||||
else if(lastCommandOnBank.getCommand() == Command::SREFX)
|
||||
else if (lastCommandOnBank.getCommand() == Command::SREFX)
|
||||
{
|
||||
command.delayToMeetConstraint(lastCommandOnBank.getEnd(), config.Timings.tXSR);
|
||||
}
|
||||
@@ -72,11 +72,16 @@ void ActivateChecker::delay_to_satisfy_activateToActivate_sameBank(ScheduledComm
|
||||
|
||||
bool ActivateChecker::satsfies_activateToActivate_differentBank(ScheduledCommand& command) const
|
||||
{
|
||||
for (sc_time time : state.lastActivates)
|
||||
for (auto act : state.lastActivates)
|
||||
{
|
||||
if ((time < command.getStart() && command.getStart() - time < config.Timings.tRRD)
|
||||
|| (command.getStart() <= time && time - command.getStart() < config.Timings.tRRD))
|
||||
return false;
|
||||
sc_time time = act.first;
|
||||
sc_time tRRD =
|
||||
(getBankGroup(command.getBank()) == getBankGroup(act.second)) ?
|
||||
config.Timings.tRRD_L : config.Timings.tRRD_S;
|
||||
|
||||
if ((time < command.getStart() && command.getStart() - time < tRRD)
|
||||
|| (command.getStart() <= time && time - command.getStart() < tRRD))
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
@@ -90,15 +95,15 @@ bool ActivateChecker::satisfies_nActivateWindow(ScheduledCommand& command) const
|
||||
*/
|
||||
if (state.lastActivates.size() >= config.nActivate)
|
||||
{
|
||||
set<sc_time> lastActivates = state.lastActivates;
|
||||
lastActivates.emplace(command.getStart());
|
||||
map<sc_time, Bank> lastActivates = state.lastActivates;
|
||||
lastActivates.emplace(command.getStart(), command.getBank());
|
||||
auto upper = lastActivates.begin();
|
||||
advance(upper, config.nActivate);
|
||||
auto lower = lastActivates.begin();
|
||||
|
||||
while (upper != lastActivates.end())
|
||||
{
|
||||
if (*upper - *lower < config.Timings.tNAW)
|
||||
if (upper->first - lower->first < config.Timings.tNAW)
|
||||
return false;
|
||||
++upper;
|
||||
++lower;
|
||||
|
||||
@@ -85,7 +85,11 @@ bool ReadChecker::collidesWithStrobeCommand(ScheduledCommand& read,
|
||||
//write to read
|
||||
else
|
||||
{
|
||||
return !(read.getStart()>= getIntervalOnDataStrobe(strobeCommand).end + config.Timings.tWTR);
|
||||
sc_time tWTR =
|
||||
(getBankGroup(read.getBank()) == getBankGroup(strobeCommand.getBank())) ?
|
||||
config.Timings.tWTR_L : config.Timings.tWTR_S;
|
||||
|
||||
return !(read.getStart()>= getIntervalOnDataStrobe(strobeCommand).end + tWTR);
|
||||
}
|
||||
}
|
||||
else
|
||||
|
||||
@@ -82,8 +82,12 @@ bool WriteChecker::collidesWithStrobeCommand(ScheduledCommand& write,
|
||||
//write to read
|
||||
if (strobeCommand.getStart() >= write.getStart())
|
||||
{
|
||||
sc_time tWTR =
|
||||
(getBankGroup(write.getBank()) == getBankGroup(strobeCommand.getBank())) ?
|
||||
config.Timings.tWTR_L : config.Timings.tWTR_S;
|
||||
|
||||
return !(strobeCommand.getStart()
|
||||
>= getIntervalOnDataStrobe(write).end + config.Timings.tWTR);
|
||||
>= getIntervalOnDataStrobe(write).end + tWTR);
|
||||
}
|
||||
|
||||
//read to write
|
||||
|
||||
@@ -70,4 +70,20 @@ bool TimeInterval::intersects(TimeInterval other)
|
||||
return other.timeIsInInterval(this->start) || this->timeIsInInterval(other.start);
|
||||
}
|
||||
|
||||
BankGroup getBankGroup(Bank bank)
|
||||
{
|
||||
static std::map<Bank, BankGroup> bankgroups;
|
||||
if (bankgroups.size() == 0)
|
||||
{
|
||||
SC_ASSERT_(config.NumberOfBanks % config.NumberOfBankGroups == 0, "Number of banks must be a multiple of number of bankgroups");
|
||||
|
||||
for (unsigned int bank = 0; bank < Configuration::getInstance().NumberOfBanks; bank++)
|
||||
{
|
||||
unsigned int group = bank / Configuration::getInstance().NumberOfBankGroups;
|
||||
bankgroups.insert(std::pair<Bank, BankGroup>(Bank(bank), BankGroup(group)));
|
||||
}
|
||||
}
|
||||
return bankgroups.at(bank);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -34,6 +34,7 @@ enum Alignment {UP, DOWN};
|
||||
const sc_time clkAlign(sc_time time, sc_time clk, Alignment alignment = UP);
|
||||
bool isClkAligned(sc_time time, sc_time clk);
|
||||
|
||||
BankGroup getBankGroup(Bank bank);
|
||||
|
||||
};
|
||||
#endif /* UTILS_H_ */
|
||||
|
||||
Reference in New Issue
Block a user