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 */ 35 36#include "CommandAnalysis.h" 37 38using std::cerr; 39using std::endl; 40using std::max; 41 42using namespace Data; 43 44 45int64_t zero_guard(int64_t cycles_in, const char* warning) 46{ 47 // Calculate max(0, cycles_in) 48 int64_t zero = 0; 49 if (warning != nullptr && cycles_in < 0) { 50 // This line is commented out for now, we will attempt to remove the situations where 51 // these warnings trigger later. 52 // cerr << "WARNING: " << warning << endl; 53 } 54 return max(zero, cycles_in); 55} 56 57void CommandAnalysis::handleAct(unsigned bank, int64_t timestamp) 58{ 59 printWarningIfPoweredDown("Command issued while in power-down mode.", MemCommand::ACT, timestamp, bank); 60 // If command is ACT - update number of acts, bank state of the 61 // target bank, first and latest activation cycle and the memory 62 // state. Update the number of precharged/idle-precharged cycles. 63 // If the bank is already active ignore the command and generate a 64 // warning. 65 if (isPrecharged(bank)) { 66 numberofactsBanks[bank]++; 67 68 if (nActiveBanks() == 0) { 69 // Here a memory state transition to ACT is happening. Save the 70 // number of cycles in precharge state (increment the counter). 71 first_act_cycle = timestamp; 72 precycles += zero_guard(timestamp - last_pre_cycle, "1 last_pre_cycle is in the future."); 73 idle_pre_update(timestamp, latest_pre_cycle); 74 } 75 76 bank_state[bank] = BANK_ACTIVE; 77 latest_act_cycle = timestamp; 78 } else { 79 printWarning("Bank is already active!", MemCommand::ACT, timestamp, bank); 80 } 81} 82 83void CommandAnalysis::handleRd(unsigned bank, int64_t timestamp) 84{ 85 printWarningIfPoweredDown("Command issued while in power-down mode.", MemCommand::RD, timestamp, bank); 86 // If command is RD - update number of reads and read cycle. Check 87 // for active idle cycles (if any). 88 if (isPrecharged(bank)) { 89 printWarning("Bank is not active!", MemCommand::RD, timestamp, bank); 90 } 91 numberofreadsBanks[bank]++; 92 idle_act_update(latest_read_cycle, latest_write_cycle, latest_act_cycle, timestamp); 93 latest_read_cycle = timestamp; 94} 95 96void CommandAnalysis::handleWr(unsigned bank, int64_t timestamp) 97{ 98 printWarningIfPoweredDown("Command issued while in power-down mode.", MemCommand::WR, timestamp, bank); 99 // If command is WR - update number of writes and write cycle. Check 100 // for active idle cycles (if any). 101 if (isPrecharged(bank)) { 102 printWarning("Bank is not active!", MemCommand::WR, timestamp, bank); 103 } 104 numberofwritesBanks[bank]++; 105 idle_act_update(latest_read_cycle, latest_write_cycle, latest_act_cycle, timestamp); 106 latest_write_cycle = timestamp; 107} 108 109void CommandAnalysis::handleRef(unsigned bank, int64_t timestamp) 110{ 111 printWarningIfPoweredDown("Command issued while in power-down mode.", MemCommand::REF, timestamp, bank); 112 // If command is REF - update number of refreshes, set bank state of 113 // all banks to ACT, set the last PRE cycles at RFC-RP cycles from 114 // timestamp, set the number of active cycles to RFC-RP and check 115 // for active and precharged cycles and idle active and idle 116 // precharged cycles before refresh. Change memory state to 0. 117 printWarningIfActive("One or more banks are active! REF requires all banks to be precharged.", MemCommand::REF, timestamp, bank); 118 numberofrefs++; 119 idle_pre_update(timestamp, latest_pre_cycle); 120 first_act_cycle = timestamp; 121 std::fill(first_act_cycle_banks.begin(), first_act_cycle_banks.end(), timestamp); 122 precycles += zero_guard(timestamp - last_pre_cycle, "2 last_pre_cycle is in the future."); 123 last_pre_cycle = timestamp + memSpec.memTimingSpec.RFC - memSpec.memTimingSpec.RP; 124 latest_pre_cycle = last_pre_cycle; 125 actcycles += memSpec.memTimingSpec.RFC - memSpec.memTimingSpec.RP; 126 for (auto &e : actcyclesBanks) { 127 e += memSpec.memTimingSpec.RFC - memSpec.memTimingSpec.RP; 128 } 129 for (auto& bs : bank_state) { 130 bs = BANK_PRECHARGED; 131 } 132} 133 134void CommandAnalysis::handleRefB(unsigned bank, int64_t timestamp) 135{ 136 // A REFB command requires a previous PRE command. 137 if (isPrecharged(bank)) { 138 // This previous PRE command handler is also responsible for keeping the 139 // memory state updated. 140 // Here we consider that the memory state is not changed in order to keep 141 // things simple, since the transition from PRE to ACT state takes time. 142 numberofrefbBanks[bank]++; 143 // Length of the refresh: here we have an approximation, we consider tRP 144 // also as act cycles because the bank will be precharged (stable) after 145 // tRP. 146 actcyclesBanks[bank] += memSpec.memTimingSpec.RAS + memSpec.memTimingSpec.RP; 147 } else { 148 printWarning("Bank must be precharged for REFB!", MemCommand::REFB, timestamp, bank); 149 } 150} 151 152void CommandAnalysis::handlePre(unsigned bank, int64_t timestamp) 153{ 154 printWarningIfPoweredDown("Command issued while in power-down mode.", MemCommand::PRE, timestamp, bank); 155 // If command is explicit PRE - update number of precharges, bank 156 // state of the target bank and last and latest precharge cycle. 157 // Calculate the number of active cycles if the memory was in the 158 // active state before, but there is a state transition to PRE now 159 // (i.e., this is the last active bank). 160 // If the bank is already precharged ignore the command and generate a 161 // warning. 162 163 // Precharge only if the target bank is active 164 if (bank_state[bank] == BANK_ACTIVE) { 165 numberofpresBanks[bank]++; 166 actcyclesBanks[bank] += zero_guard(timestamp - first_act_cycle_banks[bank], "first_act_cycle is in the future (bank)."); 167 // Since we got here, at least one bank is active 168 assert(nActiveBanks() != 0); 169 170 if (nActiveBanks() == 1) { 171 // This is the last active bank. Therefore, here a memory state 172 // transition to PRE is happening. Let's increment the active cycle 173 // counter. 174 actcycles += zero_guard(timestamp - first_act_cycle, "first_act_cycle is in the future."); 175 last_pre_cycle = timestamp; 176 idle_act_update(latest_read_cycle, latest_write_cycle, latest_act_cycle, timestamp); 177 } 178 179 bank_state[bank] = BANK_PRECHARGED; 180 latest_pre_cycle = timestamp; 181 } else { 182 printWarning("Bank is already precharged!", MemCommand::PRE, timestamp, bank); 183 } 184} 185 186void CommandAnalysis::handlePreA(unsigned bank, int64_t timestamp) 187{ 188 printWarningIfPoweredDown("Command issued while in power-down mode.", MemCommand::PREA, timestamp, bank); 189 // If command is explicit PREA (precharge all banks) - update 190 // number of precharges by the number of active banks, update the bank 191 // state of all banks to PRE and set the precharge cycle (the cycle in 192 // which the memory state changes from ACT to PRE, aka last_pre_cycle). 193 // Calculate the number of active cycles if the memory was in the 194 // active state before, but there is a state transition to PRE now. 195 196 if (nActiveBanks() > 0) { 197 // Active banks are being precharged 198 // At least one bank was active, therefore the current memory state is 199 // ACT. Since all banks are being precharged a memory state transition 200 // to PRE is happening. Add to the counter the amount of cycles the 201 // memory remained in the ACT state. 202 203 actcycles += zero_guard(timestamp - first_act_cycle, "first_act_cycle is in the future."); 204 last_pre_cycle = timestamp; 205 206 for (unsigned b = 0; b < num_banks; b++) { 207 if (bank_state[b] == BANK_ACTIVE) { 208 // Active banks are being precharged 209 numberofpresBanks[b] += 1; 210 actcyclesBanks[b] += zero_guard(timestamp - first_act_cycle_banks[b], "first_act_cycle is in the future (bank)."); 211 } 212 } 213 214 idle_act_update(latest_read_cycle, latest_write_cycle, latest_act_cycle, timestamp); 215 216 latest_pre_cycle = timestamp; 217 // Reset the state for all banks to precharged. 218 for (auto& bs : bank_state) { 219 bs = BANK_PRECHARGED; 220 } 221 } else { 222 printWarning("All banks are already precharged!", MemCommand::PREA, timestamp, bank); 223 } 224} 225 226void CommandAnalysis::handlePdnFAct(unsigned bank, int64_t timestamp) 227{ 228 // If command is fast-exit active power-down - update number of 229 // power-downs, set the power-down cycle and the memory mode to 230 // fast-exit active power-down. Save states of all the banks from 231 // the cycle before entering active power-down, to be returned to 232 // after powering-up. Update active and active idle cycles. 233 printWarningIfNotActive("All banks are precharged! Incorrect use of Active Power-Down.", MemCommand::PDN_F_ACT, timestamp, bank); 234 f_act_pdns++; 235 last_bank_state = bank_state; 236 pdn_cycle = timestamp; 237 actcycles += zero_guard(timestamp - first_act_cycle, "first_act_cycle is in the future."); 238 for (unsigned b = 0; b < num_banks; b++) { 239 if (bank_state[b] == BANK_ACTIVE) { 240 actcyclesBanks[b] += zero_guard(timestamp - first_act_cycle_banks[b], "first_act_cycle is in the future (bank)."); 241 } 242 } 243 idle_act_update(latest_read_cycle, latest_write_cycle, latest_act_cycle, timestamp); 244 mem_state = CommandAnalysis::MS_PDN_F_ACT; 245} 246 247void CommandAnalysis::handlePdnSAct(unsigned bank, int64_t timestamp) 248{ 249 // If command is slow-exit active power-down - update number of 250 // power-downs, set the power-down cycle and the memory mode to 251 // slow-exit active power-down. Save states of all the banks from 252 // the cycle before entering active power-down, to be returned to 253 // after powering-up. Update active and active idle cycles. 254 printWarningIfNotActive("All banks are precharged! Incorrect use of Active Power-Down.", MemCommand::PDN_S_ACT, timestamp, bank); 255 s_act_pdns++; 256 last_bank_state = bank_state; 257 pdn_cycle = timestamp; 258 actcycles += zero_guard(timestamp - first_act_cycle, "first_act_cycle is in the future."); 259 for (unsigned b = 0; b < num_banks; b++) { 260 if (bank_state[b] == BANK_ACTIVE) { 261 actcyclesBanks[b] += zero_guard(timestamp - first_act_cycle_banks[b], "first_act_cycle is in the future (bank)."); 262 } 263 } 264 idle_act_update(latest_read_cycle, latest_write_cycle, latest_act_cycle, timestamp); 265 mem_state = CommandAnalysis::MS_PDN_S_ACT; 266} 267 268void CommandAnalysis::handlePdnFPre(unsigned bank, int64_t timestamp) 269{ 270 // If command is fast-exit precharged power-down - update number of 271 // power-downs, set the power-down cycle and the memory mode to 272 // fast-exit precahrged power-down. Update precharged and precharged 273 // idle cycles. 274 printWarningIfActive("One or more banks are active! Incorrect use of Precharged Power-Down.", MemCommand::PDN_F_PRE, timestamp, bank); 275 f_pre_pdns++; 276 pdn_cycle = timestamp; 277 precycles += zero_guard(timestamp - last_pre_cycle, "3 last_pre_cycle is in the future."); 278 idle_pre_update(timestamp, latest_pre_cycle); 279 mem_state = CommandAnalysis::MS_PDN_F_PRE; 280} 281 282void CommandAnalysis::handlePdnSPre(unsigned bank, int64_t timestamp) 283{ 284 // If command is slow-exit precharged power-down - update number of 285 // power-downs, set the power-down cycle and the memory mode to 286 // slow-exit precahrged power-down. Update precharged and precharged 287 // idle cycles. 288 printWarningIfActive("One or more banks are active! Incorrect use of Precharged Power-Down.", MemCommand::PDN_S_PRE, timestamp, bank); 289 s_pre_pdns++; 290 pdn_cycle = timestamp; 291 precycles += zero_guard(timestamp - last_pre_cycle, "4 last_pre_cycle is in the future."); 292 idle_pre_update(timestamp, latest_pre_cycle); 293 mem_state = CommandAnalysis::MS_PDN_S_PRE; 294} 295 296void CommandAnalysis::handlePupAct(int64_t timestamp) 297{ 298 // If command is power-up in the active mode - check the power-down 299 // exit-mode employed (fast or slow), update the number of power-down 300 // and power-up cycles and the latest and first act cycle. Also, reset 301 // all the individual bank states to the respective saved states 302 // before entering power-down. 303 const MemTimingSpec& t = memSpec.memTimingSpec; 304 305 if (mem_state == CommandAnalysis::MS_PDN_F_ACT) { 306 f_act_pdcycles += zero_guard(timestamp - pdn_cycle, "pdn_cycle is in the future."); 307 pup_act_cycles += t.XP; 308 latest_act_cycle = timestamp; 309 } else if (mem_state == CommandAnalysis::MS_PDN_S_ACT) { 310 s_act_pdcycles += zero_guard(timestamp - pdn_cycle, "pdn_cycle is in the future."); 311 if (memSpec.memArchSpec.dll == false) { 312 pup_act_cycles += t.XP; 313 latest_act_cycle = timestamp; 314 } else { 315 pup_act_cycles += t.XPDLL - t.RCD; 316 latest_act_cycle = timestamp + zero_guard(t.XPDLL - (2 * t.RCD), "t.XPDLL - (2 * t.RCD) < 0"); 317 } 318 } else { 319 cerr << "Incorrect use of Active Power-Up!" << endl; 320 } 321 mem_state = MS_NOT_IN_PD; 322 bank_state = last_bank_state; 323 first_act_cycle = timestamp; 324 std::fill(first_act_cycle_banks.begin(), first_act_cycle_banks.end(), timestamp); 325} 326 327void CommandAnalysis::handlePupPre(int64_t timestamp) 328{ 329 // If command is power-up in the precharged mode - check the power-down 330 // exit-mode employed (fast or slow), update the number of power-down 331 // and power-up cycles and the latest and last pre cycle. 332 const MemTimingSpec& t = memSpec.memTimingSpec; 333 if (mem_state == CommandAnalysis::MS_PDN_F_PRE) { 334 f_pre_pdcycles += zero_guard(timestamp - pdn_cycle, "pdn_cycle is in the future."); 335 pup_pre_cycles += t.XP; 336 latest_pre_cycle = timestamp; 337 } else if (mem_state == CommandAnalysis::MS_PDN_S_PRE) { 338 s_pre_pdcycles += zero_guard(timestamp - pdn_cycle, "pdn_cycle is in the future."); 339 if (memSpec.memArchSpec.dll == false) { 340 pup_pre_cycles += t.XP; 341 latest_pre_cycle = timestamp; 342 } else { 343 pup_pre_cycles += t.XPDLL - t.RCD; 344 latest_pre_cycle = timestamp + zero_guard(t.XPDLL - t.RCD - t.RP, "t.XPDLL - t.RCD - t.RP"); 345 } 346 } else { 347 cerr << "Incorrect use of Precharged Power-Up!" << endl; 348 } 349 mem_state = MS_NOT_IN_PD; 350 last_pre_cycle = timestamp; 351} 352 353void CommandAnalysis::handleSREn(unsigned bank, int64_t timestamp) 354{ 355 // If command is self-refresh - update number of self-refreshes, 356 // set memory state to SREF, update precharge and idle precharge 357 // cycles and set the self-refresh cycle. 358 printWarningIfActive("One or more banks are active! SREF requires all banks to be precharged.", MemCommand::SREN, timestamp, bank); 359 numberofsrefs++; 360 sref_cycle = timestamp; 361 sref_cycle_window = timestamp; 362 sref_ref_pre_cycles_window = 0; 363 sref_ref_act_cycles_window = 0; 364 precycles += zero_guard(timestamp - last_pre_cycle, "5 last_pre_cycle is in the future."); 365 idle_pre_update(timestamp, latest_pre_cycle); 366 mem_state = CommandAnalysis::MS_SREF; 367} 368 369void CommandAnalysis::handleSREx(unsigned bank, int64_t timestamp) 370{ 371 // If command is self-refresh exit - update the number of self-refresh 372 // clock cycles, number of active and precharged auto-refresh clock 373 // cycles during self-refresh and self-refresh exit based on the number 374 // of cycles in the self-refresh mode and auto-refresh duration (RFC). 375 // Set the last and latest precharge cycle accordingly and set the 376 // memory state to 0. 377 const MemTimingSpec& t = memSpec.memTimingSpec; 378 if (mem_state != CommandAnalysis::MS_SREF) { 379 cerr << "Incorrect use of Self-Refresh Power-Up!" << endl; 380 } 381 // The total duration of self-refresh is given by the difference between 382 // the current clock cycle and the clock cycle of entering self-refresh. 383 int64_t sref_duration = timestamp - sref_cycle; 384 385 // Negative or zero duration should never happen. 386 if (sref_duration <= 0) { 387 printWarning("Invalid Self-Refresh duration!", MemCommand::SREX, timestamp, bank); 388 sref_duration = 0; 389 } 390 391 // The minimum time that the DRAM must remain in Self-Refresh is CKESR. 392 if (sref_duration < t.CKESR) { 393 printWarning("Self-Refresh duration < CKESR!", MemCommand::SREX, timestamp, bank); 394 } 395 396 if (sref_duration >= t.RFC) { 397 /* 398 * Self-refresh Exit Context 1 (tSREF >= tRFC): 399 * The memory remained in self-refresh for a certain number of clock 400 * cycles greater than a refresh cycle time (RFC). Consequently, the 401 * initial auto-refresh accomplished. 402 * 403 * 404 * SREN # SREX 405 * | # ^ 406 * | # | 407 * |<------------------------- tSREF ----------...----->| 408 * | # | 409 * | Initial Auto-Refresh # | 410 * v # | 411 * ------------------------------------#-------...-----------------> t 412 * # 413 * <------------- tRFC --------------># 414 * <---- (tRFC - tRP) ----><-- tRP --># 415 * | | 416 * v v 417 * sref_ref_act_cycles sref_ref_pre_cycles 418 * 419 * 420 * Summary: 421 * sref_cycles += tSREF – tRFC 422 * sref_ref_act_cycles += tRFC - tRP 423 * sref_ref_pre_cycles += tRP 424 * spup_ref_act_cycles += 0 425 * spup_ref_pre_cycles += 0 426 * 427 */ 428 429 // The initial auto-refresh consumes (IDD5 − IDD3N) over one refresh 430 // period (RFC) from the start of the self-refresh. 431 sref_ref_act_cycles += t.RFC - 432 t.RP - sref_ref_act_cycles_window; 433 sref_ref_pre_cycles += t.RP - sref_ref_pre_cycles_window; 434 last_pre_cycle = timestamp; 435 436 // The IDD6 current is consumed for the time period spent in the 437 // self-refresh mode, which excludes the time spent in finishing the 438 // initial auto-refresh. 439 if (sref_cycle_window > sref_cycle + t.RFC) { 440 sref_cycles += zero_guard(timestamp - sref_cycle_window, "sref_cycle_window is in the future."); 441 } else { 442 sref_cycles += zero_guard(timestamp - sref_cycle - t.RFC, "sref_cycle - t.RFC < 0"); 443 } 444 445 // IDD2N current is consumed when exiting the self-refresh state. 446 if (memSpec.memArchSpec.dll == false) { 447 spup_cycles += t.XS; 448 latest_pre_cycle = timestamp + zero_guard(t.XS - t.RP, "t.XS - t.RP < 0"); 449 } else { 450 spup_cycles += t.XSDLL - t.RCD; 451 latest_pre_cycle = timestamp + zero_guard(t.XSDLL - t.RCD - t.RP, "t.XSDLL - t.RCD - t.RP < 0"); 452 } 453 454 } else { 455 // Self-refresh Exit Context 2 (tSREF < tRFC): 456 // Exit self-refresh before the completion of the initial 457 // auto-refresh. 458 459 // Number of active cycles needed by an auto-refresh. 460 int64_t ref_act_cycles = t.RFC - t.RP; 461 462 if (sref_duration >= ref_act_cycles) { 463 /* 464 * Self-refresh Exit Context 2A (tSREF < tRFC && tSREF >= tRFC - tRP): 465 * The duration of self-refresh is equal or greater than the number 466 * of active cycles needed by the initial auto-refresh. 467 * 468 * 469 * SREN SREX 470 * | ^ # 471 * | | # 472 * |<------------------ tSREF --------------------->| # 473 * | | # 474 * | Initial Auto-Refresh # 475 * v | # 476 * -----------------------------------------------------------#--> t 477 * # 478 * <------------------------ tRFC --------------------------># 479 * <------------- (tRFC - tRP)--------------><----- tRP ----># 480 * | <-----><-------> 481 * v | | 482 * sref_ref_act_cycles v v 483 * sref_ref_pre_cycles spup_ref_pre_cycles 484 * 485 * 486 * Summary: 487 * sref_cycles += 0 488 * sref_ref_act_cycles += tRFC - tRP 489 * sref_ref_pre_cycles += tSREF – (tRFC – tRP) 490 * spup_ref_act_cycles += 0 491 * spup_ref_pre_cycles += tRP – sref_ref_pre_cycles 492 * 493 */ 494 495 // Number of precharged cycles (zero <= pre_cycles < RP) 496 int64_t pre_cycles = sref_duration - ref_act_cycles - sref_ref_pre_cycles_window; 497 498 sref_ref_act_cycles += ref_act_cycles - sref_ref_act_cycles_window; 499 sref_ref_pre_cycles += pre_cycles; 500 501 // Number of precharged cycles during the self-refresh power-up. It 502 // is at maximum tRP (if pre_cycles is zero). 503 int64_t spup_pre = t.RP - pre_cycles; 504 505 spup_ref_pre_cycles += spup_pre; 506 507 last_pre_cycle = timestamp + spup_pre; 508 509 if (memSpec.memArchSpec.dll == false) { 510 spup_cycles += t.XS - spup_pre; 511 latest_pre_cycle = timestamp + zero_guard(t.XS - spup_pre - t.RP, "t.XS - spup_pre - t.RP < 0"); 512 } else { 513 spup_cycles += t.XSDLL - t.RCD - spup_pre; 514 latest_pre_cycle = timestamp + zero_guard(t.XSDLL - t.RCD - spup_pre - t.RP, "t.XSDLL - t.RCD - spup_pre - t.RP"); 515 } 516 } else { 517 /* 518 * Self-refresh Exit Context 2B (tSREF < tRFC - tRP): 519 * self-refresh duration is shorter than the number of active cycles 520 * needed by the initial auto-refresh. 521 * 522 * 523 * SREN SREX 524 * | ^ # 525 * | | # 526 * |<-------------- tSREF ----------->| # 527 * | | # 528 * | Initial Auto-Refresh # 529 * v | # 530 * ------------------------------------------------------------#--> t 531 * # 532 * <------------------------ tRFC ---------------------------># 533 * <-------------- (tRFC - tRP)-------------><------ tRP ----># 534 * <--------------------------------><------><---------------> 535 * | | | 536 * v v v 537 * sref_ref_act_cycles spup_ref_act_cycles spup_ref_pre_cycles 538 * 539 * 540 * Summary: 541 * sref_cycles += 0 542 * sref_ref_act_cycles += tSREF 543 * sref_ref_pre_cycles += 0 544 * spup_ref_act_cycles += (tRFC – tRP) - tSREF 545 * spup_ref_pre_cycles += tRP 546 * 547 */ 548 549 sref_ref_act_cycles += sref_duration - sref_ref_act_cycles_window; 550 551 int64_t spup_act = (t.RFC - t.RP) - sref_duration; 552 553 spup_ref_act_cycles += spup_act; 554 spup_ref_pre_cycles += t.RP; 555 556 last_pre_cycle = timestamp + spup_act + t.RP; 557 if (memSpec.memArchSpec.dll == false) { 558 spup_cycles += t.XS - spup_act - t.RP; 559 latest_pre_cycle = timestamp + zero_guard(t.XS - spup_act - (2 * t.RP), "t.XS - spup_act - (2 * t.RP) < 0"); 560 } else { 561 spup_cycles += t.XSDLL - t.RCD - spup_act - t.RP; 562 latest_pre_cycle = timestamp + zero_guard(t.XSDLL - t.RCD - spup_act - (2 * t.RP), "t.XSDLL - t.RCD - spup_act - (2 * t.RP) < 0"); 563 } 564 } 565 } 566 mem_state = MS_NOT_IN_PD; 567} 568 569 570void CommandAnalysis::handleNopEnd(int64_t timestamp) 571{ 572 // May be optionally used at the end of memory trace for better accuracy 573 // Update all counters based on completion of operations. 574 const MemTimingSpec& t = memSpec.memTimingSpec; 575 for (unsigned b = 0; b < num_banks; b++) { 576 if (bank_state[b] == BANK_ACTIVE) { 577 actcyclesBanks[b] += zero_guard(timestamp - first_act_cycle_banks[b], "first_act_cycle is in the future (bank)"); 578 } 579 } 580 581 if (nActiveBanks() > 0 && mem_state == MS_NOT_IN_PD) { 582 actcycles += zero_guard(timestamp - first_act_cycle, "first_act_cycle is in the future"); 583 idle_act_update(latest_read_cycle, latest_write_cycle, 584 latest_act_cycle, timestamp); 585 } else if (nActiveBanks() == 0 && mem_state == MS_NOT_IN_PD) { 586 precycles += zero_guard(timestamp - last_pre_cycle, "6 last_pre_cycle is in the future"); 587 idle_pre_update(timestamp, latest_pre_cycle); 588 } else if (mem_state == CommandAnalysis::MS_PDN_F_ACT) { 589 f_act_pdcycles += zero_guard(timestamp - pdn_cycle, "pdn_cycle is in the future"); 590 } else if (mem_state == CommandAnalysis::MS_PDN_S_ACT) { 591 s_act_pdcycles += zero_guard(timestamp - pdn_cycle, "pdn_cycle is in the future"); 592 } else if (mem_state == CommandAnalysis::MS_PDN_F_PRE) { 593 f_pre_pdcycles += zero_guard(timestamp - pdn_cycle, "pdn_cycle is in the future"); 594 } else if (mem_state == CommandAnalysis::MS_PDN_S_PRE) { 595 s_pre_pdcycles += zero_guard(timestamp - pdn_cycle, "pdn_cycle is in the future"); 596 } else if (mem_state == CommandAnalysis::MS_SREF) { 597 auto rfc_minus_rp = (t.RFC - t.RP); 598 599 if (timestamp > sref_cycle + t.RFC) { 600 if (sref_cycle_window <= sref_cycle + rfc_minus_rp) { 601 sref_ref_act_cycles += rfc_minus_rp - sref_ref_act_cycles_window; 602 sref_ref_act_cycles_window = rfc_minus_rp; 603 sref_cycle_window = sref_cycle + rfc_minus_rp; 604 } 605 if (sref_cycle_window <= sref_cycle + t.RFC) { 606 sref_ref_pre_cycles += t.RP - sref_ref_pre_cycles_window; 607 sref_ref_pre_cycles_window = t.RP; 608 sref_cycle_window = sref_cycle + t.RFC; 609 } 610 sref_cycles += zero_guard(timestamp - sref_cycle_window, "sref_cycle_window is in the future"); 611 } else if (timestamp > sref_cycle + rfc_minus_rp) { 612 613 if (sref_cycle_window <= sref_cycle + rfc_minus_rp) { 614 sref_ref_act_cycles += rfc_minus_rp - sref_ref_act_cycles_window; 615 sref_ref_act_cycles_window = rfc_minus_rp; 616 sref_cycle_window = sref_cycle + rfc_minus_rp; 617 } 618 sref_ref_pre_cycles_window += timestamp - sref_cycle_window; 619 sref_ref_pre_cycles += timestamp - sref_cycle_window; 620 } else { 621 sref_ref_act_cycles_window += timestamp - sref_cycle_window; 622 sref_ref_act_cycles += timestamp - sref_cycle_window; 623 } 624 } 625} 626