mem: Sort memory commands and update DRAMPower
Add local variable to stores commands to be issued. These commands are in order within a single bank but will be out of order across banks & ranks. A new procedure, flushCmdList, sorts commands across banks / ranks, and flushes the sorted list, up to curTick() to DRAMPower. This is currently called in refresh, once all previous commands are guaranteed to have completed. Could be called in other events like the powerEvent as well. By only flushing commands up to curTick(), will not get out of sync when flushed at a periodic stats dump (done in subsequent patch). Change-Id: I4ac65a52407f64270db1e16a1fb04cfe7f638851 Reviewed-by: Radhika Jagtap <radhika.jagtap@arm.com>
This commit is contained in:
parent
61b2b493d4
commit
27665af26d
2 changed files with 89 additions and 40 deletions
|
@ -1,5 +1,5 @@
|
||||||
/*
|
/*
|
||||||
* Copyright (c) 2010-2015 ARM Limited
|
* Copyright (c) 2010-2016 ARM Limited
|
||||||
* All rights reserved
|
* All rights reserved
|
||||||
*
|
*
|
||||||
* The license below extends only to copyright in the software and shall
|
* The license below extends only to copyright in the software and shall
|
||||||
|
@ -898,9 +898,8 @@ DRAMCtrl::activateBank(Rank& rank_ref, Bank& bank_ref,
|
||||||
bank_ref.bank, rank_ref.rank, act_tick,
|
bank_ref.bank, rank_ref.rank, act_tick,
|
||||||
ranks[rank_ref.rank]->numBanksActive);
|
ranks[rank_ref.rank]->numBanksActive);
|
||||||
|
|
||||||
rank_ref.power.powerlib.doCommand(MemCommand::ACT, bank_ref.bank,
|
rank_ref.cmdList.push_back(Command(MemCommand::ACT, bank_ref.bank,
|
||||||
divCeil(act_tick, tCK) -
|
act_tick));
|
||||||
timeStampOffset);
|
|
||||||
|
|
||||||
DPRINTF(DRAMPower, "%llu,ACT,%d,%d\n", divCeil(act_tick, tCK) -
|
DPRINTF(DRAMPower, "%llu,ACT,%d,%d\n", divCeil(act_tick, tCK) -
|
||||||
timeStampOffset, bank_ref.bank, rank_ref.rank);
|
timeStampOffset, bank_ref.bank, rank_ref.rank);
|
||||||
|
@ -1002,9 +1001,8 @@ DRAMCtrl::prechargeBank(Rank& rank_ref, Bank& bank, Tick pre_at, bool trace)
|
||||||
|
|
||||||
if (trace) {
|
if (trace) {
|
||||||
|
|
||||||
rank_ref.power.powerlib.doCommand(MemCommand::PRE, bank.bank,
|
rank_ref.cmdList.push_back(Command(MemCommand::PRE, bank.bank,
|
||||||
divCeil(pre_at, tCK) -
|
pre_at));
|
||||||
timeStampOffset);
|
|
||||||
DPRINTF(DRAMPower, "%llu,PRE,%d,%d\n", divCeil(pre_at, tCK) -
|
DPRINTF(DRAMPower, "%llu,PRE,%d,%d\n", divCeil(pre_at, tCK) -
|
||||||
timeStampOffset, bank.bank, rank_ref.rank);
|
timeStampOffset, bank.bank, rank_ref.rank);
|
||||||
}
|
}
|
||||||
|
@ -1176,8 +1174,20 @@ DRAMCtrl::doDRAMAccess(DRAMPacket* dram_pkt)
|
||||||
MemCommand::cmds command = (mem_cmd == "RD") ? MemCommand::RD :
|
MemCommand::cmds command = (mem_cmd == "RD") ? MemCommand::RD :
|
||||||
MemCommand::WR;
|
MemCommand::WR;
|
||||||
|
|
||||||
|
// Update bus state
|
||||||
|
busBusyUntil = dram_pkt->readyTime;
|
||||||
|
|
||||||
|
DPRINTF(DRAM, "Access to %lld, ready at %lld bus busy until %lld.\n",
|
||||||
|
dram_pkt->addr, dram_pkt->readyTime, busBusyUntil);
|
||||||
|
|
||||||
|
dram_pkt->rankRef.cmdList.push_back(Command(command, dram_pkt->bank,
|
||||||
|
cmd_at));
|
||||||
|
|
||||||
|
DPRINTF(DRAMPower, "%llu,%s,%d,%d\n", divCeil(cmd_at, tCK) -
|
||||||
|
timeStampOffset, mem_cmd, dram_pkt->bank, dram_pkt->rank);
|
||||||
|
|
||||||
// if this access should use auto-precharge, then we are
|
// if this access should use auto-precharge, then we are
|
||||||
// closing the row
|
// closing the row after the read/write burst
|
||||||
if (auto_precharge) {
|
if (auto_precharge) {
|
||||||
// if auto-precharge push a PRE command at the correct tick to the
|
// if auto-precharge push a PRE command at the correct tick to the
|
||||||
// list used by DRAMPower library to calculate power
|
// list used by DRAMPower library to calculate power
|
||||||
|
@ -1186,19 +1196,6 @@ DRAMCtrl::doDRAMAccess(DRAMPacket* dram_pkt)
|
||||||
DPRINTF(DRAM, "Auto-precharged bank: %d\n", dram_pkt->bankId);
|
DPRINTF(DRAM, "Auto-precharged bank: %d\n", dram_pkt->bankId);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Update bus state
|
|
||||||
busBusyUntil = dram_pkt->readyTime;
|
|
||||||
|
|
||||||
DPRINTF(DRAM, "Access to %lld, ready at %lld bus busy until %lld.\n",
|
|
||||||
dram_pkt->addr, dram_pkt->readyTime, busBusyUntil);
|
|
||||||
|
|
||||||
dram_pkt->rankRef.power.powerlib.doCommand(command, dram_pkt->bank,
|
|
||||||
divCeil(cmd_at, tCK) -
|
|
||||||
timeStampOffset);
|
|
||||||
|
|
||||||
DPRINTF(DRAMPower, "%llu,%s,%d,%d\n", divCeil(cmd_at, tCK) -
|
|
||||||
timeStampOffset, mem_cmd, dram_pkt->bank, dram_pkt->rank);
|
|
||||||
|
|
||||||
// Update the minimum timing between the requests, this is a
|
// Update the minimum timing between the requests, this is a
|
||||||
// conservative estimate of when we have to schedule the next
|
// conservative estimate of when we have to schedule the next
|
||||||
// request to not introduce any unecessary bubbles. In most cases
|
// request to not introduce any unecessary bubbles. In most cases
|
||||||
|
@ -1558,6 +1555,34 @@ DRAMCtrl::Rank::checkDrainDone()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
DRAMCtrl::Rank::flushCmdList()
|
||||||
|
{
|
||||||
|
// at the moment sort the list of commands and update the counters
|
||||||
|
// for DRAMPower libray when doing a refresh
|
||||||
|
sort(cmdList.begin(), cmdList.end(), DRAMCtrl::sortTime);
|
||||||
|
|
||||||
|
auto next_iter = cmdList.begin();
|
||||||
|
// push to commands to DRAMPower
|
||||||
|
for ( ; next_iter != cmdList.end() ; ++next_iter) {
|
||||||
|
Command cmd = *next_iter;
|
||||||
|
if (cmd.timeStamp <= curTick()) {
|
||||||
|
// Move all commands at or before curTick to DRAMPower
|
||||||
|
power.powerlib.doCommand(cmd.type, cmd.bank,
|
||||||
|
divCeil(cmd.timeStamp, memory.tCK) -
|
||||||
|
memory.timeStampOffset);
|
||||||
|
} else {
|
||||||
|
// done - found all commands at or before curTick()
|
||||||
|
// next_iter references the 1st command after curTick
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// reset cmdList to only contain commands after curTick
|
||||||
|
// if there are no commands after curTick, updated cmdList will be empty
|
||||||
|
// in this case, next_iter is cmdList.end()
|
||||||
|
cmdList.assign(next_iter, cmdList.end());
|
||||||
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
DRAMCtrl::Rank::processActivateEvent()
|
DRAMCtrl::Rank::processActivateEvent()
|
||||||
{
|
{
|
||||||
|
@ -1645,9 +1670,7 @@ DRAMCtrl::Rank::processRefreshEvent()
|
||||||
}
|
}
|
||||||
|
|
||||||
// precharge all banks in rank
|
// precharge all banks in rank
|
||||||
power.powerlib.doCommand(MemCommand::PREA, 0,
|
cmdList.push_back(Command(MemCommand::PREA, 0, pre_at));
|
||||||
divCeil(pre_at, memory.tCK) -
|
|
||||||
memory.timeStampOffset);
|
|
||||||
|
|
||||||
DPRINTF(DRAMPower, "%llu,PREA,0,%d\n",
|
DPRINTF(DRAMPower, "%llu,PREA,0,%d\n",
|
||||||
divCeil(pre_at, memory.tCK) -
|
divCeil(pre_at, memory.tCK) -
|
||||||
|
@ -1683,14 +1706,11 @@ DRAMCtrl::Rank::processRefreshEvent()
|
||||||
}
|
}
|
||||||
|
|
||||||
// at the moment this affects all ranks
|
// at the moment this affects all ranks
|
||||||
power.powerlib.doCommand(MemCommand::REF, 0,
|
cmdList.push_back(Command(MemCommand::REF, 0, curTick()));
|
||||||
divCeil(curTick(), memory.tCK) -
|
|
||||||
memory.timeStampOffset);
|
|
||||||
|
|
||||||
// at the moment sort the list of commands and update the counters
|
// All commands up to refresh have completed
|
||||||
// for DRAMPower libray when doing a refresh
|
// flush cmdList to DRAMPower
|
||||||
sort(power.powerlib.cmdList.begin(),
|
flushCmdList();
|
||||||
power.powerlib.cmdList.end(), DRAMCtrl::sortTime);
|
|
||||||
|
|
||||||
// update the counters for DRAMPower, passing false to
|
// update the counters for DRAMPower, passing false to
|
||||||
// indicate that this is not the last command in the
|
// indicate that this is not the last command in the
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
/*
|
/*
|
||||||
* Copyright (c) 2012-2015 ARM Limited
|
* Copyright (c) 2012-2016 ARM Limited
|
||||||
* All rights reserved
|
* All rights reserved
|
||||||
*
|
*
|
||||||
* The license below extends only to copyright in the software and shall
|
* The license below extends only to copyright in the software and shall
|
||||||
|
@ -146,6 +146,21 @@ class DRAMCtrl : public AbstractMemory
|
||||||
|
|
||||||
BusState busState;
|
BusState busState;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Simple structure to hold the values needed to keep track of
|
||||||
|
* commands for DRAMPower
|
||||||
|
*/
|
||||||
|
struct Command {
|
||||||
|
Data::MemCommand::cmds type;
|
||||||
|
uint8_t bank;
|
||||||
|
Tick timeStamp;
|
||||||
|
|
||||||
|
constexpr Command(Data::MemCommand::cmds _type, uint8_t _bank,
|
||||||
|
Tick time_stamp)
|
||||||
|
: type(_type), bank(_bank), timeStamp(time_stamp)
|
||||||
|
{ }
|
||||||
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* A basic class to track the bank state, i.e. what row is
|
* A basic class to track the bank state, i.e. what row is
|
||||||
* currently open (if any), when is the bank free to accept a new
|
* currently open (if any), when is the bank free to accept a new
|
||||||
|
@ -316,6 +331,14 @@ class DRAMCtrl : public AbstractMemory
|
||||||
*/
|
*/
|
||||||
DRAMPower power;
|
DRAMPower power;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* List of comamnds issued, to be sent to DRAMPpower at refresh
|
||||||
|
* and stats dump. Keep commands here since commands to different
|
||||||
|
* banks are added out of order. Will only pass commands up to
|
||||||
|
* curTick() to DRAMPower after sorting.
|
||||||
|
*/
|
||||||
|
std::vector<Command> cmdList;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Vector of Banks. Each rank is made of several devices which in
|
* Vector of Banks. Each rank is made of several devices which in
|
||||||
* term are made from several banks.
|
* term are made from several banks.
|
||||||
|
@ -364,6 +387,14 @@ class DRAMCtrl : public AbstractMemory
|
||||||
*/
|
*/
|
||||||
void checkDrainDone();
|
void checkDrainDone();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Push command out of cmdList queue that are scheduled at
|
||||||
|
* or before curTick() to DRAMPower library
|
||||||
|
* All commands before curTick are guaranteed to be complete
|
||||||
|
* and can safely be flushed.
|
||||||
|
*/
|
||||||
|
void flushCmdList();
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Function to register Stats
|
* Function to register Stats
|
||||||
*/
|
*/
|
||||||
|
@ -857,18 +888,16 @@ class DRAMCtrl : public AbstractMemory
|
||||||
void updatePowerStats(Rank& rank_ref);
|
void updatePowerStats(Rank& rank_ref);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Function for sorting commands in the command list of DRAMPower.
|
* Function for sorting Command structures based on timeStamp
|
||||||
*
|
*
|
||||||
* @param a Memory Command in command list of DRAMPower library
|
* @param a Memory Command
|
||||||
* @param next Memory Command in command list of DRAMPower
|
* @param next Memory Command
|
||||||
* @return true if timestamp of Command 1 < timestamp of Command 2
|
* @return true if timeStamp of Command 1 < timeStamp of Command 2
|
||||||
*/
|
*/
|
||||||
static bool sortTime(const Data::MemCommand& m1,
|
static bool sortTime(const Command& cmd, const Command& cmd_next) {
|
||||||
const Data::MemCommand& m2) {
|
return cmd.timeStamp < cmd_next.timeStamp;
|
||||||
return m1.getTimeInt64() < m2.getTimeInt64();
|
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
public:
|
public:
|
||||||
|
|
||||||
void regStats() override;
|
void regStats() override;
|
||||||
|
|
Loading…
Reference in a new issue