CommandAnalysis.cc revision 11555
1/* 2 * Copyright (c) 2012-2014, TU Delft 3 * Copyright (c) 2012-2014, TU Eindhoven 4 * Copyright (c) 2012-2014, TU Kaiserslautern 5 * All rights reserved. 6 * 7 * Redistribution and use in source and binary forms, with or without 8 * modification, are permitted provided that the following conditions are 9 * met: 10 * 11 * 1. Redistributions of source code must retain the above copyright 12 * notice, this list of conditions and the following disclaimer. 13 * 14 * 2. Redistributions in binary form must reproduce the above copyright 15 * notice, this list of conditions and the following disclaimer in the 16 * documentation and/or other materials provided with the distribution. 17 * 18 * 3. Neither the name of the copyright holder nor the names of its 19 * contributors may be used to endorse or promote products derived from 20 * this software without specific prior written permission. 21 * 22 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS 23 * IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED 24 * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A 25 * PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 26 * HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 27 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED 28 * TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR 29 * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF 30 * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING 31 * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS 32 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 33 * 34 * Authors: Karthik Chandrasekar, Matthias Jung, Omar Naji, Sven Goossens 35 * 36 */ 37 38#include <fstream> 39#include <algorithm> 40#include <sstream> 41 42#include "CommandAnalysis.h" 43#include "CmdScheduler.h" 44 45using namespace Data; 46using namespace std; 47 48bool commandSorter(const MemCommand& i, const MemCommand& j) 49{ 50 if (i.getTimeInt64() == j.getTimeInt64()) { 51 return i.getType() == MemCommand::PRE && j.getType() != MemCommand::PRE; 52 } else { 53 return i.getTimeInt64() < j.getTimeInt64(); 54 } 55} 56 57CommandAnalysis::CommandAnalysis(const int64_t nbrofBanks) 58{ 59 // Initializing all counters and variables 60 clearStats(0); 61 zero = 0; 62 63 bankstate.resize(static_cast<size_t>(nbrofBanks), 0); 64 last_states.resize(static_cast<size_t>(nbrofBanks)); 65 mem_state = 0; 66 num_active_banks = 0; 67 68 cmd_list.clear(); 69 cached_cmd.clear(); 70 activation_cycle.resize(static_cast<size_t>(nbrofBanks), 0); 71} 72 73// function to clear counters 74void CommandAnalysis::clearStats(const int64_t timestamp) 75{ 76 77 numberofacts = 0; 78 numberofpres = 0; 79 numberofreads = 0; 80 numberofwrites = 0; 81 numberofrefs = 0; 82 f_act_pdns = 0; 83 s_act_pdns = 0; 84 f_pre_pdns = 0; 85 s_pre_pdns = 0; 86 numberofsrefs = 0; 87 88 actcycles = 0; 89 precycles = 0; 90 f_act_pdcycles = 0; 91 s_act_pdcycles = 0; 92 f_pre_pdcycles = 0; 93 s_pre_pdcycles = 0; 94 pup_act_cycles = 0; 95 pup_pre_cycles = 0; 96 sref_cycles = 0; 97 spup_cycles = 0; 98 sref_ref_act_cycles = 0; 99 sref_ref_pre_cycles = 0; 100 spup_ref_act_cycles = 0; 101 spup_ref_pre_cycles = 0; 102 idlecycles_act = 0; 103 idlecycles_pre = 0; 104 105 // reset count references to timestamp so that they are moved 106 // to start of next stats generation 107 first_act_cycle = timestamp; 108 last_pre_cycle = timestamp; 109 pdn_cycle = timestamp; 110 sref_cycle = timestamp; 111 end_act_op = timestamp; 112 end_read_op = timestamp; 113 end_write_op = timestamp; 114 115 latest_act_cycle = -1; 116 latest_read_cycle = -1; 117 latest_write_cycle = -1; 118 119 if (timestamp == 0) { 120 // set to -1 at beginning of simulation 121 latest_pre_cycle = -1; 122 } else { 123 // NOTE: reference is adjusted by tRP (PRE delay) when updating counter 124 // could remove tRP to ensure counter starts at beginning of next block; 125 // currently simply setting to timestamp for simplicity 126 latest_pre_cycle = timestamp; 127 } 128} 129 130// function to clear all arrays 131void CommandAnalysis::clear() 132{ 133 cached_cmd.clear(); 134 cmd_list.clear(); 135 last_states.clear(); 136 bankstate.clear(); 137} 138 139// Reads through the trace file, identifies the timestamp, command and bank 140// If the issued command includes an auto-precharge, adds an explicit 141// precharge to a cached command list and computes the precharge offset from the 142// issued command timestamp, when the auto-precharge would kick in 143 144void CommandAnalysis::getCommands(const Data::MemorySpecification& memSpec, 145 std::vector<MemCommand>& list, bool lastupdate) 146{ 147 for (size_t i = 0; i < list.size(); ++i) { 148 MemCommand& cmd = list[i]; 149 MemCommand::cmds cmdType = cmd.getType(); 150 if (cmdType == MemCommand::ACT) { 151 activation_cycle[cmd.getBank()] = cmd.getTimeInt64(); 152 } else if (cmdType == MemCommand::RDA || cmdType == MemCommand::WRA) { 153 // Remove auto-precharge flag from command 154 cmd.setType(cmd.typeWithoutAutoPrechargeFlag()); 155 156 // Add the auto precharge to the list of cached_cmds 157 int64_t preTime = max(cmd.getTimeInt64() + cmd.getPrechargeOffset(memSpec, cmdType), 158 activation_cycle[cmd.getBank()] + memSpec.memTimingSpec.RAS); 159 list.push_back(MemCommand(MemCommand::PRE, cmd.getBank(), preTime)); 160 } 161 } 162 sort(list.begin(), list.end(), commandSorter); 163 164 if (lastupdate && list.empty() == false) { 165 // Add cycles at the end of the list 166 int64_t t = timeToCompletion(memSpec, list.back().getType()) + list.back().getTimeInt64() - 1; 167 list.push_back(MemCommand(MemCommand::NOP, 0, t)); 168 } 169 170 evaluate(memSpec, list); 171} // CommandAnalysis::getCommands 172 173 174// To get the time of completion of the issued command 175// Derived based on JEDEC specifications 176 177int64_t CommandAnalysis::timeToCompletion(const MemorySpecification& 178 memSpec, MemCommand::cmds type) 179{ 180 int64_t offset = 0; 181 const MemTimingSpec& memTimingSpec = memSpec.memTimingSpec; 182 const MemArchitectureSpec& memArchSpec = memSpec.memArchSpec; 183 184 if (type == MemCommand::RD) { 185 offset = memTimingSpec.RL + 186 memTimingSpec.DQSCK + 1 + (memArchSpec.burstLength / 187 memArchSpec.dataRate); 188 } else if (type == MemCommand::WR) { 189 offset = memTimingSpec.WL + 190 (memArchSpec.burstLength / memArchSpec.dataRate) + 191 memTimingSpec.WR; 192 } else if (type == MemCommand::ACT) { 193 offset = memTimingSpec.RCD; 194 } else if ((type == MemCommand::PRE) || (type == MemCommand::PREA)) { 195 offset = memTimingSpec.RP; 196 } 197 return offset; 198} // CommandAnalysis::timeToCompletion 199 200// Used to analyse a given list of commands and identify command timings 201// and memory state transitions 202void CommandAnalysis::evaluate(const MemorySpecification& memSpec, 203 vector<MemCommand>& cmd_list) 204{ 205 // for each command identify timestamp, type and bank 206 for (auto cmd : cmd_list) { 207 // For command type 208 int type = cmd.getType(); 209 // For command bank 210 int bank = static_cast<int>(cmd.getBank()); 211 // Command Issue timestamp in clock cycles (cc) 212 int64_t timestamp = cmd.getTimeInt64(); 213 214 if (type == MemCommand::ACT) { 215 printWarningIfPoweredDown("Command issued while in power-down mode.", type, timestamp, bank); 216 // If command is ACT - update number of acts, bank state of the 217 // target bank, first and latest activation cycle and the memory 218 // state. Update the number of precharged/idle-precharged cycles. 219 numberofacts++; 220 if (bankstate[static_cast<size_t>(bank)] == 1) { 221 printWarning("Bank is already active!", type, timestamp, bank); 222 } 223 bankstate[static_cast<size_t>(bank)] = 1; 224 if (num_active_banks == 0) { 225 first_act_cycle = timestamp; 226 precycles += max(zero, timestamp - last_pre_cycle); 227 idle_pre_update(memSpec, timestamp, latest_pre_cycle); 228 } 229 latest_act_cycle = timestamp; 230 num_active_banks++; 231 } else if (type == MemCommand::RD) { 232 printWarningIfPoweredDown("Command issued while in power-down mode.", type, timestamp, bank); 233 // If command is RD - update number of reads and read cycle. Check 234 // for active idle cycles (if any). 235 if (bankstate[static_cast<size_t>(bank)] == 0) { 236 printWarning("Bank is not active!", type, timestamp, bank); 237 } 238 numberofreads++; 239 idle_act_update(memSpec, latest_read_cycle, latest_write_cycle, 240 latest_act_cycle, timestamp); 241 latest_read_cycle = timestamp; 242 } else if (type == MemCommand::WR) { 243 printWarningIfPoweredDown("Command issued while in power-down mode.", type, timestamp, bank); 244 // If command is WR - update number of writes and write cycle. Check 245 // for active idle cycles (if any). 246 if (bankstate[static_cast<size_t>(bank)] == 0) { 247 printWarning("Bank is not active!", type, timestamp, bank); 248 } 249 numberofwrites++; 250 idle_act_update(memSpec, latest_read_cycle, latest_write_cycle, 251 latest_act_cycle, timestamp); 252 latest_write_cycle = timestamp; 253 } else if (type == MemCommand::REF) { 254 printWarningIfPoweredDown("Command issued while in power-down mode.", type, timestamp, bank); 255 // If command is REF - update number of refreshes, set bank state of 256 // all banks to ACT, set the last PRE cycles at RFC-RP cycles from 257 // timestamp, set the number of active cycles to RFC-RP and check 258 // for active and precharged cycles and idle active and idle 259 // precharged cycles before refresh. Change memory state to 0. 260 printWarningIfActive("One or more banks are active! REF requires all banks to be precharged.", type, timestamp, bank); 261 numberofrefs++; 262 idle_pre_update(memSpec, timestamp, latest_pre_cycle); 263 first_act_cycle = timestamp; 264 precycles += max(zero, timestamp - last_pre_cycle); 265 last_pre_cycle = timestamp + memSpec.memTimingSpec.RFC - 266 memSpec.memTimingSpec.RP; 267 latest_pre_cycle = last_pre_cycle; 268 actcycles += memSpec.memTimingSpec.RFC - memSpec.memTimingSpec.RP; 269 num_active_banks = 0; 270 for (auto& b : bankstate) { 271 b = 0; 272 } 273 } else if (type == MemCommand::PRE) { 274 printWarningIfPoweredDown("Command issued while in power-down mode.", type, timestamp, bank); 275 // If command is explicit PRE - update number of precharges, bank 276 // state of the target bank and last and latest precharge cycle. 277 // Calculate the number of active cycles if the memory was in the 278 // active state before, but there is a state transition to PRE now. 279 // If not, update the number of precharged cycles and idle cycles. 280 // Update memory state if needed. 281 if (bankstate[static_cast<size_t>(bank)] == 1) { 282 numberofpres++; 283 } 284 bankstate[static_cast<size_t>(bank)] = 0; 285 286 if (num_active_banks == 1) { 287 actcycles += max(zero, timestamp - first_act_cycle); 288 last_pre_cycle = timestamp; 289 idle_act_update(memSpec, latest_read_cycle, latest_write_cycle, 290 latest_act_cycle, timestamp); 291 } else if (num_active_banks == 0) { 292 precycles += max(zero, timestamp - last_pre_cycle); 293 idle_pre_update(memSpec, timestamp, latest_pre_cycle); 294 last_pre_cycle = timestamp; 295 } 296 latest_pre_cycle = timestamp; 297 if (num_active_banks > 0) { 298 num_active_banks--; 299 } else { 300 num_active_banks = 0; 301 } 302 } else if (type == MemCommand::PREA) { 303 printWarningIfPoweredDown("Command issued while in power-down mode.", type, timestamp, bank); 304 // If command is explicit PREA (precharge all banks) - update 305 // number of precharges by the number of banks, update the bank 306 // state of all banks to PRE and set the precharge cycle. 307 // Calculate the number of active cycles if the memory was in the 308 // active state before, but there is a state transition to PRE now. 309 // If not, update the number of precharged cycles and idle cycles. 310 numberofpres += num_active_banks; 311 312 if (num_active_banks > 0) { 313 actcycles += max(zero, timestamp - first_act_cycle); 314 idle_act_update(memSpec, latest_read_cycle, latest_write_cycle, 315 latest_act_cycle, timestamp); 316 } else if (num_active_banks == 0) { 317 precycles += max(zero, timestamp - last_pre_cycle); 318 idle_pre_update(memSpec, timestamp, latest_pre_cycle); 319 } 320 321 latest_pre_cycle = timestamp; 322 last_pre_cycle = timestamp; 323 324 num_active_banks = 0; 325 326 for (auto& b : bankstate) { 327 b = 0; 328 } 329 } else if (type == MemCommand::PDN_F_ACT) { 330 // If command is fast-exit active power-down - update number of 331 // power-downs, set the power-down cycle and the memory mode to 332 // fast-exit active power-down. Save states of all the banks from 333 // the cycle before entering active power-down, to be returned to 334 // after powering-up. Update active and active idle cycles. 335 printWarningIfNotActive("All banks are precharged! Incorrect use of Active Power-Down.", type, timestamp, bank); 336 f_act_pdns++; 337 last_states = bankstate; 338 pdn_cycle = timestamp; 339 actcycles += max(zero, timestamp - first_act_cycle); 340 idle_act_update(memSpec, latest_read_cycle, latest_write_cycle, 341 latest_act_cycle, timestamp); 342 mem_state = CommandAnalysis::MS_PDN_F_ACT; 343 } else if (type == MemCommand::PDN_S_ACT) { 344 // If command is slow-exit active power-down - update number of 345 // power-downs, set the power-down cycle and the memory mode to 346 // slow-exit active power-down. Save states of all the banks from 347 // the cycle before entering active power-down, to be returned to 348 // after powering-up. Update active and active idle cycles. 349 printWarningIfNotActive("All banks are precharged! Incorrect use of Active Power-Down.", type, timestamp, bank); 350 s_act_pdns++; 351 last_states = bankstate; 352 pdn_cycle = timestamp; 353 actcycles += max(zero, timestamp - first_act_cycle); 354 idle_act_update(memSpec, latest_read_cycle, latest_write_cycle, 355 latest_act_cycle, timestamp); 356 mem_state = CommandAnalysis::MS_PDN_S_ACT; 357 } else if (type == MemCommand::PDN_F_PRE) { 358 // If command is fast-exit precharged power-down - update number of 359 // power-downs, set the power-down cycle and the memory mode to 360 // fast-exit precahrged power-down. Update precharged and precharged 361 // idle cycles. 362 printWarningIfActive("One or more banks are active! Incorrect use of Precharged Power-Down.", type, timestamp, bank); 363 f_pre_pdns++; 364 pdn_cycle = timestamp; 365 precycles += max(zero, timestamp - last_pre_cycle); 366 idle_pre_update(memSpec, timestamp, latest_pre_cycle); 367 mem_state = CommandAnalysis::MS_PDN_F_PRE; 368 } else if (type == MemCommand::PDN_S_PRE) { 369 // If command is slow-exit precharged power-down - update number of 370 // power-downs, set the power-down cycle and the memory mode to 371 // slow-exit precahrged power-down. Update precharged and precharged 372 // idle cycles. 373 printWarningIfActive("One or more banks are active! Incorrect use of Precharged Power-Down.", type, timestamp, bank); 374 s_pre_pdns++; 375 pdn_cycle = timestamp; 376 precycles += max(zero, timestamp - last_pre_cycle); 377 idle_pre_update(memSpec, timestamp, latest_pre_cycle); 378 mem_state = CommandAnalysis::MS_PDN_S_PRE; 379 } else if (type == MemCommand::PUP_ACT) { 380 // If command is power-up in the active mode - check the power-down 381 // exit-mode employed (fast or slow), update the number of power-down 382 // and power-up cycles and the latest and first act cycle. Also, reset 383 // all the individual bank states to the respective saved states 384 // before entering power-down. 385 if (mem_state == CommandAnalysis::MS_PDN_F_ACT) { 386 f_act_pdcycles += max(zero, timestamp - pdn_cycle); 387 pup_act_cycles += memSpec.memTimingSpec.XP; 388 latest_act_cycle = max(timestamp, timestamp + 389 memSpec.memTimingSpec.XP - memSpec.memTimingSpec.RCD); 390 } else if (mem_state == CommandAnalysis::MS_PDN_S_ACT) { 391 s_act_pdcycles += max(zero, timestamp - pdn_cycle); 392 if (memSpec.memArchSpec.dll == false) { 393 pup_act_cycles += memSpec.memTimingSpec.XP; 394 latest_act_cycle = max(timestamp, timestamp + 395 memSpec.memTimingSpec.XP - memSpec.memTimingSpec.RCD); 396 } else { 397 pup_act_cycles += memSpec.memTimingSpec.XPDLL - 398 memSpec.memTimingSpec.RCD; 399 latest_act_cycle = max(timestamp, timestamp + 400 memSpec.memTimingSpec.XPDLL - 401 (2 * memSpec.memTimingSpec.RCD)); 402 } 403 } else if (mem_state != CommandAnalysis::MS_PDN_S_ACT || mem_state != CommandAnalysis::MS_PDN_F_ACT) { 404 cerr << "Incorrect use of Active Power-Up!" << endl; 405 } 406 num_active_banks = 0; 407 mem_state = 0; 408 bankstate = last_states; 409 for (auto& a : last_states) { 410 num_active_banks += static_cast<unsigned int>(a); 411 } 412 first_act_cycle = timestamp; 413 } else if (type == MemCommand::PUP_PRE) { 414 // If command is power-up in the precharged mode - check the power-down 415 // exit-mode employed (fast or slow), update the number of power-down 416 // and power-up cycles and the latest and last pre cycle. 417 if (mem_state == CommandAnalysis::MS_PDN_F_PRE) { 418 f_pre_pdcycles += max(zero, timestamp - pdn_cycle); 419 pup_pre_cycles += memSpec.memTimingSpec.XP; 420 latest_pre_cycle = max(timestamp, timestamp + 421 memSpec.memTimingSpec.XP - memSpec.memTimingSpec.RP); 422 } else if (mem_state == CommandAnalysis::MS_PDN_S_PRE) { 423 s_pre_pdcycles += max(zero, timestamp - pdn_cycle); 424 if (memSpec.memArchSpec.dll == false) { 425 pup_pre_cycles += memSpec.memTimingSpec.XP; 426 latest_pre_cycle = max(timestamp, timestamp + 427 memSpec.memTimingSpec.XP - memSpec.memTimingSpec.RP); 428 } else { 429 pup_pre_cycles += memSpec.memTimingSpec.XPDLL - 430 memSpec.memTimingSpec.RCD; 431 latest_pre_cycle = max(timestamp, timestamp + 432 memSpec.memTimingSpec.XPDLL - memSpec.memTimingSpec.RCD - 433 memSpec.memTimingSpec.RP); 434 } 435 } else if (mem_state != CommandAnalysis::MS_PDN_S_PRE || mem_state != CommandAnalysis::MS_PDN_F_PRE) { 436 cerr << "Incorrect use of Precharged Power-Up!" << endl; 437 } 438 mem_state = 0; 439 num_active_banks = 0; 440 last_pre_cycle = timestamp; 441 } else if (type == MemCommand::SREN) { 442 // If command is self-refresh - update number of self-refreshes, 443 // set memory state to SREF, update precharge and idle precharge 444 // cycles and set the self-refresh cycle. 445 printWarningIfActive("One or more banks are active! SREF requires all banks to be precharged.", type, timestamp, bank); 446 numberofsrefs++; 447 sref_cycle = timestamp; 448 precycles += max(zero, timestamp - last_pre_cycle); 449 idle_pre_update(memSpec, timestamp, latest_pre_cycle); 450 mem_state = CommandAnalysis::MS_SREF; 451 } else if (type == MemCommand::SREX) { 452 // If command is self-refresh exit - update the number of self-refresh 453 // clock cycles, number of active and precharged auto-refresh clock 454 // cycles during self-refresh and self-refresh exit based on the number 455 // of cycles in the self-refresh mode and auto-refresh duration (RFC). 456 // Set the last and latest precharge cycle accordingly and set the 457 // memory state to 0. 458 if (mem_state != CommandAnalysis::MS_SREF) { 459 cerr << "Incorrect use of Self-Refresh Power-Up!" << endl; 460 } 461 if (max(zero, timestamp - sref_cycle) >= memSpec.memTimingSpec.RFC) { 462 sref_cycles += max(zero, timestamp - sref_cycle 463 - memSpec.memTimingSpec.RFC); 464 sref_ref_act_cycles += memSpec.memTimingSpec.RFC - 465 memSpec.memTimingSpec.RP; 466 sref_ref_pre_cycles += memSpec.memTimingSpec.RP; 467 last_pre_cycle = timestamp; 468 if (memSpec.memArchSpec.dll == false) { 469 spup_cycles += memSpec.memTimingSpec.XS; 470 latest_pre_cycle = max(timestamp, timestamp + 471 memSpec.memTimingSpec.XS - memSpec.memTimingSpec.RP); 472 } else { 473 spup_cycles += memSpec.memTimingSpec.XSDLL - 474 memSpec.memTimingSpec.RCD; 475 latest_pre_cycle = max(timestamp, timestamp + 476 memSpec.memTimingSpec.XSDLL - memSpec.memTimingSpec.RCD 477 - memSpec.memTimingSpec.RP); 478 } 479 } else { 480 int64_t sref_diff = memSpec.memTimingSpec.RFC - memSpec.memTimingSpec.RP; 481 int64_t sref_pre = max(zero, timestamp - sref_cycle - sref_diff); 482 int64_t spup_pre = memSpec.memTimingSpec.RP - sref_pre; 483 int64_t sref_act = max(zero, timestamp - sref_cycle); 484 int64_t spup_act = memSpec.memTimingSpec.RFC - sref_act; 485 486 if (max(zero, timestamp - sref_cycle) >= sref_diff) { 487 sref_ref_act_cycles += sref_diff; 488 sref_ref_pre_cycles += sref_pre; 489 spup_ref_pre_cycles += spup_pre; 490 last_pre_cycle = timestamp + spup_pre; 491 if (memSpec.memArchSpec.dll == false) { 492 spup_cycles += memSpec.memTimingSpec.XS - spup_pre; 493 latest_pre_cycle = max(timestamp, timestamp + 494 memSpec.memTimingSpec.XS - spup_pre - 495 memSpec.memTimingSpec.RP); 496 } else { 497 spup_cycles += memSpec.memTimingSpec.XSDLL - 498 memSpec.memTimingSpec.RCD - spup_pre; 499 latest_pre_cycle = max(timestamp, timestamp + 500 memSpec.memTimingSpec.XSDLL - memSpec.memTimingSpec.RCD - 501 spup_pre - memSpec.memTimingSpec.RP); 502 } 503 } else { 504 sref_ref_act_cycles += sref_act; 505 spup_ref_act_cycles += spup_act; 506 spup_ref_pre_cycles += memSpec.memTimingSpec.RP; 507 last_pre_cycle = timestamp + spup_act + memSpec.memTimingSpec.RP; 508 if (memSpec.memArchSpec.dll == false) { 509 spup_cycles += memSpec.memTimingSpec.XS - spup_act - 510 memSpec.memTimingSpec.RP; 511 latest_pre_cycle = max(timestamp, timestamp + 512 memSpec.memTimingSpec.XS - spup_act - 513 (2 * memSpec.memTimingSpec.RP)); 514 } else { 515 spup_cycles += memSpec.memTimingSpec.XSDLL - 516 memSpec.memTimingSpec.RCD - spup_act - 517 memSpec.memTimingSpec.RP; 518 latest_pre_cycle = max(timestamp, timestamp + 519 memSpec.memTimingSpec.XSDLL - memSpec.memTimingSpec.RCD - 520 spup_act - (2 * memSpec.memTimingSpec.RP)); 521 } 522 } 523 } 524 mem_state = 0; 525 num_active_banks = 0; 526 } else if (type == MemCommand::END || type == MemCommand::NOP) { 527 // May be optionally used at the end of memory trace for better accuracy 528 // Update all counters based on completion of operations. 529 if (num_active_banks > 0 && mem_state == 0) { 530 actcycles += max(zero, timestamp - first_act_cycle); 531 idle_act_update(memSpec, latest_read_cycle, latest_write_cycle, 532 latest_act_cycle, timestamp); 533 } else if (num_active_banks == 0 && mem_state == 0) { 534 precycles += max(zero, timestamp - last_pre_cycle); 535 idle_pre_update(memSpec, timestamp, latest_pre_cycle); 536 } else if (mem_state == CommandAnalysis::MS_PDN_F_ACT) { 537 f_act_pdcycles += max(zero, timestamp - pdn_cycle); 538 } else if (mem_state == CommandAnalysis::MS_PDN_S_ACT) { 539 s_act_pdcycles += max(zero, timestamp - pdn_cycle); 540 } else if (mem_state == CommandAnalysis::MS_PDN_F_PRE) { 541 f_pre_pdcycles += max(zero, timestamp - pdn_cycle); 542 } else if (mem_state == CommandAnalysis::MS_PDN_S_PRE) { 543 s_pre_pdcycles += max(zero, timestamp - pdn_cycle); 544 } else if (mem_state == CommandAnalysis::MS_SREF) { 545 sref_cycles += max(zero, timestamp - sref_cycle); 546 } 547 } else { 548 printWarning("Unknown command given, exiting.", type, timestamp, bank); 549 exit(-1); 550 } 551 } 552} // CommandAnalysis::evaluate 553 554// To update idle period information whenever active cycles may be idle 555void CommandAnalysis::idle_act_update(const MemorySpecification& memSpec, 556 int64_t latest_read_cycle, int64_t latest_write_cycle, 557 int64_t latest_act_cycle, int64_t timestamp) 558{ 559 if (latest_read_cycle >= 0) { 560 end_read_op = latest_read_cycle + timeToCompletion(memSpec, 561 MemCommand::RD) - 1; 562 } 563 564 if (latest_write_cycle >= 0) { 565 end_write_op = latest_write_cycle + timeToCompletion(memSpec, 566 MemCommand::WR) - 1; 567 } 568 569 if (latest_act_cycle >= 0) { 570 end_act_op = latest_act_cycle + timeToCompletion(memSpec, 571 MemCommand::ACT) - 1; 572 } 573 574 idlecycles_act += max(zero, timestamp - max(max(end_read_op, end_write_op), 575 end_act_op)); 576} // CommandAnalysis::idle_act_update 577 578// To update idle period information whenever precharged cycles may be idle 579void CommandAnalysis::idle_pre_update(const MemorySpecification& memSpec, 580 int64_t timestamp, int64_t latest_pre_cycle) 581{ 582 if (latest_pre_cycle > 0) { 583 idlecycles_pre += max(zero, timestamp - latest_pre_cycle - 584 memSpec.memTimingSpec.RP); 585 } else if (latest_pre_cycle == 0) { 586 idlecycles_pre += max(zero, timestamp - latest_pre_cycle); 587 } 588} 589 590void CommandAnalysis::printWarningIfActive(const string& warning, int type, int64_t timestamp, int bank) 591{ 592 if (num_active_banks != 0) { 593 printWarning(warning, type, timestamp, bank); 594 } 595} 596 597void CommandAnalysis::printWarningIfNotActive(const string& warning, int type, int64_t timestamp, int bank) 598{ 599 if (num_active_banks == 0) { 600 printWarning(warning, type, timestamp, bank); 601 } 602} 603 604void CommandAnalysis::printWarningIfPoweredDown(const string& warning, int type, int64_t timestamp, int bank) 605{ 606 if (mem_state != 0) { 607 printWarning(warning, type, timestamp, bank); 608 } 609} 610 611void CommandAnalysis::printWarning(const string& warning, int type, int64_t timestamp, int bank) 612{ 613 cerr << "WARNING: " << warning << endl; 614 cerr << "Command: " << type << ", Timestamp: " << timestamp << 615 ", Bank: " << bank << endl; 616} 617