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,8 +1174,20 @@ DRAMCtrl::doDRAMAccess(DRAMPacket* dram_pkt) MemCommand::cmds command = (mem_cmd == "RD") ? MemCommand::RD : 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 - // closing the row + // 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 @@ -1186,19 +1196,6 @@ DRAMCtrl::doDRAMAccess(DRAMPacket* dram_pkt) 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 // conservative estimate of when we have to schedule the next // 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 DRAMCtrl::Rank::processActivateEvent() { @@ -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); + cmdList.push_back(Command(MemCommand::REF, 0, curTick())); - // 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); + // 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 @@ -146,6 +146,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 @@ -316,6 +331,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 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;