CommandAnalysis.cc revision 12266
16757SAli.Saidi@ARM.com/* 26757SAli.Saidi@ARM.com * Copyright (c) 2012-2014, TU Delft 36757SAli.Saidi@ARM.com * Copyright (c) 2012-2014, TU Eindhoven 46757SAli.Saidi@ARM.com * Copyright (c) 2012-2014, TU Kaiserslautern 56757SAli.Saidi@ARM.com * All rights reserved. 67090SAli.Saidi@ARM.com * 77090SAli.Saidi@ARM.com * Redistribution and use in source and binary forms, with or without 87090SAli.Saidi@ARM.com * modification, are permitted provided that the following conditions are 97090SAli.Saidi@ARM.com * met: 107090SAli.Saidi@ARM.com * 117090SAli.Saidi@ARM.com * 1. Redistributions of source code must retain the above copyright 127090SAli.Saidi@ARM.com * notice, this list of conditions and the following disclaimer. 137090SAli.Saidi@ARM.com * 147090SAli.Saidi@ARM.com * 2. Redistributions in binary form must reproduce the above copyright 156757SAli.Saidi@ARM.com * notice, this list of conditions and the following disclaimer in the 166757SAli.Saidi@ARM.com * documentation and/or other materials provided with the distribution. 176757SAli.Saidi@ARM.com * 186757SAli.Saidi@ARM.com * 3. Neither the name of the copyright holder nor the names of its 196757SAli.Saidi@ARM.com * contributors may be used to endorse or promote products derived from 206757SAli.Saidi@ARM.com * this software without specific prior written permission. 216757SAli.Saidi@ARM.com * 226757SAli.Saidi@ARM.com * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS 236757SAli.Saidi@ARM.com * IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED 246757SAli.Saidi@ARM.com * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A 256757SAli.Saidi@ARM.com * PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 266757SAli.Saidi@ARM.com * HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 276757SAli.Saidi@ARM.com * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED 286757SAli.Saidi@ARM.com * TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR 296757SAli.Saidi@ARM.com * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF 306757SAli.Saidi@ARM.com * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING 316757SAli.Saidi@ARM.com * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS 326757SAli.Saidi@ARM.com * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 336757SAli.Saidi@ARM.com * 346757SAli.Saidi@ARM.com * Authors: Karthik Chandrasekar, 356757SAli.Saidi@ARM.com * Matthias Jung, 366757SAli.Saidi@ARM.com * Omar Naji, 376757SAli.Saidi@ARM.com * Sven Goossens, 386757SAli.Saidi@ARM.com * Éder F. Zulian 396757SAli.Saidi@ARM.com * Subash Kannoth 406757SAli.Saidi@ARM.com * Felipe S. Prado 416757SAli.Saidi@ARM.com * 426757SAli.Saidi@ARM.com */ 437584SAli.Saidi@arm.com 446757SAli.Saidi@ARM.com#include <fstream> 457584SAli.Saidi@arm.com#include <algorithm> 467584SAli.Saidi@arm.com#include <sstream> 477584SAli.Saidi@arm.com 487584SAli.Saidi@arm.com#include "CommandAnalysis.h" 497584SAli.Saidi@arm.com#include "CmdScheduler.h" 507584SAli.Saidi@arm.com 517584SAli.Saidi@arm.comusing namespace Data; 527584SAli.Saidi@arm.comusing namespace std; 537584SAli.Saidi@arm.com 547695SPrakash.Ramrakhyani@arm.combool commandSorter(const MemCommand& i, const MemCommand& j) 55{ 56 if (i.getTimeInt64() == j.getTimeInt64()) { 57 return i.getType() == MemCommand::PRE && j.getType() != MemCommand::PRE; 58 } else { 59 return i.getTimeInt64() < j.getTimeInt64(); 60 } 61} 62 63CommandAnalysis::CommandAnalysis(const Data::MemorySpecification& memSpec) : 64 memSpec(memSpec) 65 66{ 67 auto &nBanks = memSpec.memArchSpec.nbrOfBanks; 68 // Initializing all counters and variables 69 numberofactsBanks.assign(static_cast<size_t>(nBanks), 0); 70 numberofpresBanks.assign(static_cast<size_t>(nBanks), 0); 71 numberofreadsBanks.assign(static_cast<size_t>(nBanks), 0); 72 numberofwritesBanks.assign(static_cast<size_t>(nBanks), 0); 73 actcyclesBanks.assign(static_cast<size_t>(nBanks), 0); 74 numberofrefbBanks.assign(static_cast<size_t>(nBanks), 0); 75 76 first_act_cycle_banks.resize(static_cast<size_t>(nBanks), 0); 77 78 clearStats(0); 79 zero = 0; 80 81 bank_state.resize(static_cast<size_t>(nBanks), BANK_PRECHARGED); 82 last_bank_state.resize(static_cast<size_t>(nBanks), BANK_PRECHARGED); 83 mem_state = MS_NOT_IN_PD; 84 85 cmd_list.clear(); 86 cached_cmd.clear(); 87 activation_cycle.resize(static_cast<size_t>(nBanks), 0); 88 num_banks = nBanks; 89} 90 91// function to clear counters 92void CommandAnalysis::clearStats(const int64_t timestamp) 93{ 94 std::fill(numberofactsBanks.begin(), numberofactsBanks.end(), 0); 95 std::fill(numberofpresBanks.begin(), numberofpresBanks.end(), 0); 96 std::fill(numberofreadsBanks.begin(), numberofreadsBanks.end(), 0); 97 std::fill(numberofwritesBanks.begin(), numberofwritesBanks.end(), 0); 98 std::fill(actcyclesBanks.begin(), actcyclesBanks.end(), 0); 99 100 numberofrefs = 0; 101 f_act_pdns = 0; 102 s_act_pdns = 0; 103 f_pre_pdns = 0; 104 s_pre_pdns = 0; 105 numberofsrefs = 0; 106 107 actcycles = 0; 108 precycles = 0; 109 f_act_pdcycles = 0; 110 s_act_pdcycles = 0; 111 f_pre_pdcycles = 0; 112 s_pre_pdcycles = 0; 113 pup_act_cycles = 0; 114 pup_pre_cycles = 0; 115 sref_cycles = 0; 116 spup_cycles = 0; 117 sref_ref_act_cycles = 0; 118 sref_ref_pre_cycles = 0; 119 spup_ref_act_cycles = 0; 120 spup_ref_pre_cycles = 0; 121 idlecycles_act = 0; 122 idlecycles_pre = 0; 123 124 // reset count references to timestamp so that they are moved 125 // to start of next stats generation 126 std::fill(first_act_cycle_banks.begin(), first_act_cycle_banks.end(), timestamp); 127 first_act_cycle = timestamp; 128 129 pdn_cycle = timestamp; 130 sref_cycle_window = timestamp; 131 132 end_act_op = timestamp; 133 end_read_op = timestamp; 134 end_write_op = timestamp; 135 136 latest_read_cycle = -1; 137 latest_write_cycle = -1; 138 139 if (timestamp == 0) { 140 latest_pre_cycle = -1; 141 latest_act_cycle = -1; 142 sref_cycle = 0; 143 last_pre_cycle = 0; 144 sref_ref_act_cycles_window = 0; 145 sref_ref_pre_cycles_window = 0; 146 } else { 147 last_pre_cycle = max(timestamp,last_pre_cycle); 148 149 latest_pre_cycle = max(timestamp, latest_pre_cycle); 150 151 if (latest_act_cycle < timestamp) 152 latest_act_cycle = -1; 153 } 154} 155 156// function to clear all arrays 157void CommandAnalysis::clear() 158{ 159 cached_cmd.clear(); 160 cmd_list.clear(); 161 last_bank_state.clear(); 162 bank_state.clear(); 163} 164 165// Reads through the trace file, identifies the timestamp, command and bank 166// If the issued command includes an auto-precharge, adds an explicit 167// precharge to a cached command list and computes the precharge offset from the 168// issued command timestamp, when the auto-precharge would kick in 169 170void CommandAnalysis::getCommands(std::vector<MemCommand>& list, bool lastupdate, int64_t timestamp) 171{ 172 if (!next_window_cmd_list.empty()) { 173 list.insert(list.begin(), next_window_cmd_list.begin(), next_window_cmd_list.end()); 174 next_window_cmd_list.clear(); 175 } 176 for (size_t i = 0; i < list.size(); ++i) { 177 MemCommand& cmd = list[i]; 178 MemCommand::cmds cmdType = cmd.getType(); 179 if (cmdType == MemCommand::ACT) { 180 activation_cycle[cmd.getBank()] = cmd.getTimeInt64(); 181 } else if (cmdType == MemCommand::RDA || cmdType == MemCommand::WRA) { 182 // Remove auto-precharge flag from command 183 cmd.setType(cmd.typeWithoutAutoPrechargeFlag()); 184 185 // Add the auto precharge to the list of cached_cmds 186 int64_t preTime = max(cmd.getTimeInt64() + cmd.getPrechargeOffset(memSpec, cmdType), 187 activation_cycle[cmd.getBank()] + memSpec.memTimingSpec.RAS); 188 list.push_back(MemCommand(MemCommand::PRE, cmd.getBank(), preTime)); 189 } 190 191 if (!lastupdate && timestamp > 0) { 192 if(cmd.getTimeInt64() > timestamp) 193 { 194 MemCommand nextWindowCmd = list[i]; 195 next_window_cmd_list.push_back(nextWindowCmd); 196 list.erase(find(list.begin(), list.end(), cmd)); 197 } 198 } 199 } 200 sort(list.begin(), list.end(), commandSorter); 201 202 if (lastupdate && list.empty() == false) { 203 // Add cycles at the end of the list 204 int64_t t = timeToCompletion(list.back().getType()) + list.back().getTimeInt64() - 1; 205 list.push_back(MemCommand(MemCommand::NOP, 0, t)); 206 } 207 208 evaluateCommands(list); 209} // CommandAnalysis::getCommands 210 211 212// Used to analyse a given list of commands and identify command timings 213// and memory state transitions 214void CommandAnalysis::evaluateCommands(vector<MemCommand>& cmd_list) 215{ 216 // for each command identify timestamp, type and bank 217 for (auto cmd : cmd_list) { 218 // For command type 219 int type = cmd.getType(); 220 // For command bank 221 unsigned bank = cmd.getBank(); 222 // Command Issue timestamp in clock cycles (cc) 223 int64_t timestamp = cmd.getTimeInt64(); 224 225 if (type == MemCommand::ACT) { 226 handleAct(bank, timestamp); 227 } else if (type == MemCommand::RD) { 228 handleRd(bank, timestamp); 229 } else if (type == MemCommand::WR) { 230 handleWr(bank, timestamp); 231 } else if (type == MemCommand::REF) { 232 handleRef(bank, timestamp); 233 } else if (type == MemCommand::REFB) { 234 handleRefB(bank, timestamp); 235 } else if (type == MemCommand::PRE) { 236 handlePre(bank, timestamp); 237 } else if (type == MemCommand::PREA) { 238 handlePreA(bank, timestamp); 239 } else if (type == MemCommand::PDN_F_ACT) { 240 handlePdnFAct(bank, timestamp); 241 } else if (type == MemCommand::PDN_S_ACT) { 242 handlePdnSAct(bank, timestamp); 243 } else if (type == MemCommand::PDN_F_PRE) { 244 handlePdnFPre(bank, timestamp); 245 } else if (type == MemCommand::PDN_S_PRE) { 246 handlePdnSPre(bank, timestamp); 247 } else if (type == MemCommand::PUP_ACT) { 248 handlePupAct(timestamp); 249 } else if (type == MemCommand::PUP_PRE) { 250 handlePupPre(timestamp); 251 } else if (type == MemCommand::SREN) { 252 handleSREn(bank, timestamp); 253 } else if (type == MemCommand::SREX) { 254 handleSREx(bank, timestamp); 255 } else if (type == MemCommand::END || type == MemCommand::NOP) { 256 handleNopEnd(timestamp); 257 } else { 258 printWarning("Unknown command given, exiting.", type, timestamp, bank); 259 exit(-1); 260 } 261 } 262} // CommandAnalysis::evaluateCommands 263 264// To update idle period information whenever active cycles may be idle 265void CommandAnalysis::idle_act_update(int64_t latest_read_cycle, int64_t latest_write_cycle, 266 int64_t latest_act_cycle, int64_t timestamp) 267{ 268 if (latest_read_cycle >= 0) { 269 end_read_op = latest_read_cycle + timeToCompletion(MemCommand::RD) - 1; 270 } 271 272 if (latest_write_cycle >= 0) { 273 end_write_op = latest_write_cycle + timeToCompletion(MemCommand::WR) - 1; 274 } 275 276 if (latest_act_cycle >= 0) { 277 end_act_op = latest_act_cycle + timeToCompletion(MemCommand::ACT) - 1; 278 } 279 280 idlecycles_act += max(zero, timestamp - max(max(end_read_op, end_write_op), 281 end_act_op)); 282} // CommandAnalysis::idle_act_update 283 284// To update idle period information whenever precharged cycles may be idle 285void CommandAnalysis::idle_pre_update(int64_t timestamp, int64_t latest_pre_cycle) 286{ 287 if (latest_pre_cycle > 0) { 288 idlecycles_pre += max(zero, timestamp - latest_pre_cycle - 289 memSpec.memTimingSpec.RP); 290 } else if (latest_pre_cycle == 0) { 291 idlecycles_pre += max(zero, timestamp - latest_pre_cycle); 292 } 293} 294 295