summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--src/mem/dram_ctrl.cc82
-rw-r--r--src/mem/dram_ctrl.hh47
2 files changed, 89 insertions, 40 deletions
diff --git a/src/mem/dram_ctrl.cc b/src/mem/dram_ctrl.cc
index 1ef311382..51131a6a7 100644
--- a/src/mem/dram_ctrl.cc
+++ b/src/mem/dram_ctrl.cc
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2010-2015 ARM Limited
+ * Copyright (c) 2010-2016 ARM Limited
* All rights reserved
*
* 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,
ranks[rank_ref.rank]->numBanksActive);
- rank_ref.power.powerlib.doCommand(MemCommand::ACT, bank_ref.bank,
- divCeil(act_tick, tCK) -
- timeStampOffset);
+ rank_ref.cmdList.push_back(Command(MemCommand::ACT, bank_ref.bank,
+ act_tick));
DPRINTF(DRAMPower, "%llu,ACT,%d,%d\n", divCeil(act_tick, tCK) -
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) {
- rank_ref.power.powerlib.doCommand(MemCommand::PRE, bank.bank,
- divCeil(pre_at, tCK) -
- timeStampOffset);
+ rank_ref.cmdList.push_back(Command(MemCommand::PRE, bank.bank,
+ pre_at));
DPRINTF(DRAMPower, "%llu,PRE,%d,%d\n", divCeil(pre_at, tCK) -
timeStampOffset, bank.bank, rank_ref.rank);
}
@@ -1176,29 +1174,28 @@ DRAMCtrl::doDRAMAccess(DRAMPacket* dram_pkt)
MemCommand::cmds command = (mem_cmd == "RD") ? MemCommand::RD :
MemCommand::WR;
- // if this access should use auto-precharge, then we are
- // closing the row
- if (auto_precharge) {
- // if auto-precharge push a PRE command at the correct tick to the
- // list used by DRAMPower library to calculate power
- prechargeBank(rank, bank, std::max(curTick(), bank.preAllowedAt));
-
- 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);
+ 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
+ // closing the row after the read/write burst
+ if (auto_precharge) {
+ // if auto-precharge push a PRE command at the correct tick to the
+ // list used by DRAMPower library to calculate power
+ prechargeBank(rank, bank, std::max(curTick(), bank.preAllowedAt));
+
+ DPRINTF(DRAM, "Auto-precharged bank: %d\n", dram_pkt->bankId);
+ }
+
// Update the minimum timing between the requests, this is a
// conservative estimate of when we have to schedule the next
// request to not introduce any unecessary bubbles. In most cases
@@ -1559,6 +1556,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
DRAMCtrl::Rank::processActivateEvent()
{
// we should transition to the active state as soon as any bank is active
@@ -1645,9 +1670,7 @@ DRAMCtrl::Rank::processRefreshEvent()
}
// precharge all banks in rank
- power.powerlib.doCommand(MemCommand::PREA, 0,
- divCeil(pre_at, memory.tCK) -
- memory.timeStampOffset);
+ cmdList.push_back(Command(MemCommand::PREA, 0, pre_at));
DPRINTF(DRAMPower, "%llu,PREA,0,%d\n",
divCeil(pre_at, memory.tCK) -
@@ -1683,14 +1706,11 @@ DRAMCtrl::Rank::processRefreshEvent()
}
// at the moment this affects all ranks
- power.powerlib.doCommand(MemCommand::REF, 0,
- divCeil(curTick(), memory.tCK) -
- memory.timeStampOffset);
-
- // at the moment sort the list of commands and update the counters
- // for DRAMPower libray when doing a refresh
- sort(power.powerlib.cmdList.begin(),
- power.powerlib.cmdList.end(), DRAMCtrl::sortTime);
+ cmdList.push_back(Command(MemCommand::REF, 0, curTick()));
+
+ // All commands up to refresh have completed
+ // flush cmdList to DRAMPower
+ flushCmdList();
// update the counters for DRAMPower, passing false to
// indicate that this is not the last command in the
diff --git a/src/mem/dram_ctrl.hh b/src/mem/dram_ctrl.hh
index 98f47edc2..70b737652 100644
--- a/src/mem/dram_ctrl.hh
+++ b/src/mem/dram_ctrl.hh
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2012-2015 ARM Limited
+ * Copyright (c) 2012-2016 ARM Limited
* All rights reserved
*
* The license below extends only to copyright in the software and shall
@@ -147,6 +147,21 @@ class DRAMCtrl : public AbstractMemory
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
* currently open (if any), when is the bank free to accept a new
* column (read/write) command, when can it be precharged, and
@@ -317,6 +332,14 @@ class DRAMCtrl : public AbstractMemory
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
* term are made from several banks.
*/
@@ -364,6 +387,14 @@ class DRAMCtrl : public AbstractMemory
*/
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
*/
@@ -857,18 +888,16 @@ class DRAMCtrl : public AbstractMemory
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 next Memory Command in command list of DRAMPower
- * @return true if timestamp of Command 1 < timestamp of Command 2
+ * @param a Memory Command
+ * @param next Memory Command
+ * @return true if timeStamp of Command 1 < timeStamp of Command 2
*/
- static bool sortTime(const Data::MemCommand& m1,
- const Data::MemCommand& m2) {
- return m1.getTimeInt64() < m2.getTimeInt64();
+ static bool sortTime(const Command& cmd, const Command& cmd_next) {
+ return cmd.timeStamp < cmd_next.timeStamp;
};
-
public:
void regStats() override;