112266Sradhika.jagtap@arm.com/*
212266Sradhika.jagtap@arm.com * Copyright (c) 2012-2014, TU Delft
312266Sradhika.jagtap@arm.com * Copyright (c) 2012-2014, TU Eindhoven
412266Sradhika.jagtap@arm.com * Copyright (c) 2012-2014, TU Kaiserslautern
512266Sradhika.jagtap@arm.com * All rights reserved.
612266Sradhika.jagtap@arm.com *
712266Sradhika.jagtap@arm.com * Redistribution and use in source and binary forms, with or without
812266Sradhika.jagtap@arm.com * modification, are permitted provided that the following conditions are
912266Sradhika.jagtap@arm.com * met:
1012266Sradhika.jagtap@arm.com *
1112266Sradhika.jagtap@arm.com * 1. Redistributions of source code must retain the above copyright
1212266Sradhika.jagtap@arm.com * notice, this list of conditions and the following disclaimer.
1312266Sradhika.jagtap@arm.com *
1412266Sradhika.jagtap@arm.com * 2. Redistributions in binary form must reproduce the above copyright
1512266Sradhika.jagtap@arm.com * notice, this list of conditions and the following disclaimer in the
1612266Sradhika.jagtap@arm.com * documentation and/or other materials provided with the distribution.
1712266Sradhika.jagtap@arm.com *
1812266Sradhika.jagtap@arm.com * 3. Neither the name of the copyright holder nor the names of its
1912266Sradhika.jagtap@arm.com * contributors may be used to endorse or promote products derived from
2012266Sradhika.jagtap@arm.com * this software without specific prior written permission.
2112266Sradhika.jagtap@arm.com *
2212266Sradhika.jagtap@arm.com * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS
2312266Sradhika.jagtap@arm.com * IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
2412266Sradhika.jagtap@arm.com * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
2512266Sradhika.jagtap@arm.com * PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
2612266Sradhika.jagtap@arm.com * HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
2712266Sradhika.jagtap@arm.com * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
2812266Sradhika.jagtap@arm.com * TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
2912266Sradhika.jagtap@arm.com * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
3012266Sradhika.jagtap@arm.com * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
3112266Sradhika.jagtap@arm.com * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
3212266Sradhika.jagtap@arm.com * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
3312266Sradhika.jagtap@arm.com *
3412266Sradhika.jagtap@arm.com */
3512266Sradhika.jagtap@arm.com
3612266Sradhika.jagtap@arm.com#include "CommandAnalysis.h"
3712266Sradhika.jagtap@arm.com
3812266Sradhika.jagtap@arm.comusing std::cerr;
3912266Sradhika.jagtap@arm.comusing std::endl;
4012266Sradhika.jagtap@arm.comusing std::max;
4112266Sradhika.jagtap@arm.com
4212266Sradhika.jagtap@arm.comusing namespace Data;
4312266Sradhika.jagtap@arm.com
4412266Sradhika.jagtap@arm.com
4512266Sradhika.jagtap@arm.comint64_t zero_guard(int64_t cycles_in, const char* warning)
4612266Sradhika.jagtap@arm.com{
4712266Sradhika.jagtap@arm.com  // Calculate max(0, cycles_in)
4812266Sradhika.jagtap@arm.com  int64_t zero = 0;
4912266Sradhika.jagtap@arm.com  if (warning != nullptr && cycles_in < 0) {
5012266Sradhika.jagtap@arm.com    // This line is commented out for now, we will attempt to remove the situations where
5112266Sradhika.jagtap@arm.com    // these warnings trigger later.
5212266Sradhika.jagtap@arm.com    // cerr << "WARNING: " << warning << endl;
5312266Sradhika.jagtap@arm.com  }
5412266Sradhika.jagtap@arm.com  return max(zero, cycles_in);
5512266Sradhika.jagtap@arm.com}
5612266Sradhika.jagtap@arm.com
5712266Sradhika.jagtap@arm.comvoid CommandAnalysis::handleAct(unsigned bank, int64_t timestamp)
5812266Sradhika.jagtap@arm.com{
5912266Sradhika.jagtap@arm.com  printWarningIfPoweredDown("Command issued while in power-down mode.", MemCommand::ACT, timestamp, bank);
6012266Sradhika.jagtap@arm.com  // If command is ACT - update number of acts, bank state of the
6112266Sradhika.jagtap@arm.com  // target bank, first and latest activation cycle and the memory
6212266Sradhika.jagtap@arm.com  // state. Update the number of precharged/idle-precharged cycles.
6312266Sradhika.jagtap@arm.com  // If the bank is already active ignore the command and generate a
6412266Sradhika.jagtap@arm.com  // warning.
6512266Sradhika.jagtap@arm.com  if (isPrecharged(bank)) {
6612266Sradhika.jagtap@arm.com    numberofactsBanks[bank]++;
6712266Sradhika.jagtap@arm.com
6812266Sradhika.jagtap@arm.com    if (nActiveBanks() == 0) {
6912266Sradhika.jagtap@arm.com      // Here a memory state transition to ACT is happening. Save the
7012266Sradhika.jagtap@arm.com      // number of cycles in precharge state (increment the counter).
7112266Sradhika.jagtap@arm.com      first_act_cycle = timestamp;
7212266Sradhika.jagtap@arm.com      precycles += zero_guard(timestamp - last_pre_cycle, "1 last_pre_cycle is in the future.");
7312266Sradhika.jagtap@arm.com      idle_pre_update(timestamp, latest_pre_cycle);
7412266Sradhika.jagtap@arm.com    }
7512266Sradhika.jagtap@arm.com
7612266Sradhika.jagtap@arm.com    bank_state[bank] = BANK_ACTIVE;
7712266Sradhika.jagtap@arm.com    latest_act_cycle = timestamp;
7812266Sradhika.jagtap@arm.com  } else {
7912266Sradhika.jagtap@arm.com    printWarning("Bank is already active!", MemCommand::ACT, timestamp, bank);
8012266Sradhika.jagtap@arm.com  }
8112266Sradhika.jagtap@arm.com}
8212266Sradhika.jagtap@arm.com
8312266Sradhika.jagtap@arm.comvoid CommandAnalysis::handleRd(unsigned bank, int64_t timestamp)
8412266Sradhika.jagtap@arm.com{
8512266Sradhika.jagtap@arm.com  printWarningIfPoweredDown("Command issued while in power-down mode.", MemCommand::RD, timestamp, bank);
8612266Sradhika.jagtap@arm.com  // If command is RD - update number of reads and read cycle. Check
8712266Sradhika.jagtap@arm.com  // for active idle cycles (if any).
8812266Sradhika.jagtap@arm.com  if (isPrecharged(bank)) {
8912266Sradhika.jagtap@arm.com    printWarning("Bank is not active!", MemCommand::RD, timestamp, bank);
9012266Sradhika.jagtap@arm.com  }
9112266Sradhika.jagtap@arm.com  numberofreadsBanks[bank]++;
9212266Sradhika.jagtap@arm.com  idle_act_update(latest_read_cycle, latest_write_cycle, latest_act_cycle, timestamp);
9312266Sradhika.jagtap@arm.com  latest_read_cycle = timestamp;
9412266Sradhika.jagtap@arm.com}
9512266Sradhika.jagtap@arm.com
9612266Sradhika.jagtap@arm.comvoid CommandAnalysis::handleWr(unsigned bank, int64_t timestamp)
9712266Sradhika.jagtap@arm.com{
9812266Sradhika.jagtap@arm.com  printWarningIfPoweredDown("Command issued while in power-down mode.", MemCommand::WR, timestamp, bank);
9912266Sradhika.jagtap@arm.com  // If command is WR - update number of writes and write cycle. Check
10012266Sradhika.jagtap@arm.com  // for active idle cycles (if any).
10112266Sradhika.jagtap@arm.com  if (isPrecharged(bank)) {
10212266Sradhika.jagtap@arm.com    printWarning("Bank is not active!", MemCommand::WR, timestamp, bank);
10312266Sradhika.jagtap@arm.com  }
10412266Sradhika.jagtap@arm.com  numberofwritesBanks[bank]++;
10512266Sradhika.jagtap@arm.com  idle_act_update(latest_read_cycle, latest_write_cycle, latest_act_cycle, timestamp);
10612266Sradhika.jagtap@arm.com  latest_write_cycle = timestamp;
10712266Sradhika.jagtap@arm.com}
10812266Sradhika.jagtap@arm.com
10912266Sradhika.jagtap@arm.comvoid CommandAnalysis::handleRef(unsigned bank, int64_t timestamp)
11012266Sradhika.jagtap@arm.com{
11112266Sradhika.jagtap@arm.com  printWarningIfPoweredDown("Command issued while in power-down mode.", MemCommand::REF, timestamp, bank);
11212266Sradhika.jagtap@arm.com  // If command is REF - update number of refreshes, set bank state of
11312266Sradhika.jagtap@arm.com  // all banks to ACT, set the last PRE cycles at RFC-RP cycles from
11412266Sradhika.jagtap@arm.com  // timestamp, set the number of active cycles to RFC-RP and check
11512266Sradhika.jagtap@arm.com  // for active and precharged cycles and idle active and idle
11612266Sradhika.jagtap@arm.com  // precharged cycles before refresh. Change memory state to 0.
11712266Sradhika.jagtap@arm.com  printWarningIfActive("One or more banks are active! REF requires all banks to be precharged.", MemCommand::REF, timestamp, bank);
11812266Sradhika.jagtap@arm.com  numberofrefs++;
11912266Sradhika.jagtap@arm.com  idle_pre_update(timestamp, latest_pre_cycle);
12012266Sradhika.jagtap@arm.com  first_act_cycle  = timestamp;
12112266Sradhika.jagtap@arm.com  std::fill(first_act_cycle_banks.begin(), first_act_cycle_banks.end(), timestamp);
12212266Sradhika.jagtap@arm.com  precycles       += zero_guard(timestamp - last_pre_cycle, "2 last_pre_cycle is in the future.");
12312266Sradhika.jagtap@arm.com  last_pre_cycle   = timestamp + memSpec.memTimingSpec.RFC - memSpec.memTimingSpec.RP;
12412266Sradhika.jagtap@arm.com  latest_pre_cycle = last_pre_cycle;
12512266Sradhika.jagtap@arm.com  actcycles       += memSpec.memTimingSpec.RFC - memSpec.memTimingSpec.RP;
12612266Sradhika.jagtap@arm.com  for (auto &e : actcyclesBanks) {
12712266Sradhika.jagtap@arm.com    e += memSpec.memTimingSpec.RFC - memSpec.memTimingSpec.RP;
12812266Sradhika.jagtap@arm.com  }
12912266Sradhika.jagtap@arm.com  for (auto& bs : bank_state) {
13012266Sradhika.jagtap@arm.com    bs = BANK_PRECHARGED;
13112266Sradhika.jagtap@arm.com  }
13212266Sradhika.jagtap@arm.com}
13312266Sradhika.jagtap@arm.com
13412266Sradhika.jagtap@arm.comvoid CommandAnalysis::handleRefB(unsigned bank, int64_t timestamp)
13512266Sradhika.jagtap@arm.com{
13612266Sradhika.jagtap@arm.com  // A REFB command requires a previous PRE command.
13712266Sradhika.jagtap@arm.com  if (isPrecharged(bank)) {
13812266Sradhika.jagtap@arm.com    // This previous PRE command handler is also responsible for keeping the
13912266Sradhika.jagtap@arm.com    // memory state updated.
14012266Sradhika.jagtap@arm.com    // Here we consider that the memory state is not changed in order to keep
14112266Sradhika.jagtap@arm.com    // things simple, since the transition from PRE to ACT state takes time.
14212266Sradhika.jagtap@arm.com    numberofrefbBanks[bank]++;
14312266Sradhika.jagtap@arm.com    // Length of the refresh: here we have an approximation, we consider tRP
14412266Sradhika.jagtap@arm.com    // also as act cycles because the bank will be precharged (stable) after
14512266Sradhika.jagtap@arm.com    // tRP.
14612266Sradhika.jagtap@arm.com    actcyclesBanks[bank] += memSpec.memTimingSpec.RAS + memSpec.memTimingSpec.RP;
14712266Sradhika.jagtap@arm.com  } else {
14812266Sradhika.jagtap@arm.com    printWarning("Bank must be precharged for REFB!", MemCommand::REFB, timestamp, bank);
14912266Sradhika.jagtap@arm.com  }
15012266Sradhika.jagtap@arm.com}
15112266Sradhika.jagtap@arm.com
15212266Sradhika.jagtap@arm.comvoid CommandAnalysis::handlePre(unsigned bank, int64_t timestamp)
15312266Sradhika.jagtap@arm.com{
15412266Sradhika.jagtap@arm.com  printWarningIfPoweredDown("Command issued while in power-down mode.", MemCommand::PRE, timestamp, bank);
15512266Sradhika.jagtap@arm.com  // If command is explicit PRE - update number of precharges, bank
15612266Sradhika.jagtap@arm.com  // state of the target bank and last and latest precharge cycle.
15712266Sradhika.jagtap@arm.com  // Calculate the number of active cycles if the memory was in the
15812266Sradhika.jagtap@arm.com  // active state before, but there is a state transition to PRE now
15912266Sradhika.jagtap@arm.com  // (i.e., this is the last active bank).
16012266Sradhika.jagtap@arm.com  // If the bank is already precharged ignore the command and generate a
16112266Sradhika.jagtap@arm.com  // warning.
16212266Sradhika.jagtap@arm.com
16312266Sradhika.jagtap@arm.com  // Precharge only if the target bank is active
16412266Sradhika.jagtap@arm.com  if (bank_state[bank] == BANK_ACTIVE) {
16512266Sradhika.jagtap@arm.com    numberofpresBanks[bank]++;
16612266Sradhika.jagtap@arm.com    actcyclesBanks[bank] += zero_guard(timestamp - first_act_cycle_banks[bank], "first_act_cycle is in the future (bank).");
16712266Sradhika.jagtap@arm.com    // Since we got here, at least one bank is active
16812266Sradhika.jagtap@arm.com    assert(nActiveBanks() != 0);
16912266Sradhika.jagtap@arm.com
17012266Sradhika.jagtap@arm.com    if (nActiveBanks() == 1) {
17112266Sradhika.jagtap@arm.com      // This is the last active bank. Therefore, here a memory state
17212266Sradhika.jagtap@arm.com      // transition to PRE is happening. Let's increment the active cycle
17312266Sradhika.jagtap@arm.com      // counter.
17412266Sradhika.jagtap@arm.com      actcycles += zero_guard(timestamp - first_act_cycle, "first_act_cycle is in the future.");
17512266Sradhika.jagtap@arm.com      last_pre_cycle = timestamp;
17612266Sradhika.jagtap@arm.com      idle_act_update(latest_read_cycle, latest_write_cycle, latest_act_cycle, timestamp);
17712266Sradhika.jagtap@arm.com    }
17812266Sradhika.jagtap@arm.com
17912266Sradhika.jagtap@arm.com    bank_state[bank] = BANK_PRECHARGED;
18012266Sradhika.jagtap@arm.com    latest_pre_cycle = timestamp;
18112266Sradhika.jagtap@arm.com  } else {
18212266Sradhika.jagtap@arm.com    printWarning("Bank is already precharged!", MemCommand::PRE, timestamp, bank);
18312266Sradhika.jagtap@arm.com  }
18412266Sradhika.jagtap@arm.com}
18512266Sradhika.jagtap@arm.com
18612266Sradhika.jagtap@arm.comvoid CommandAnalysis::handlePreA(unsigned bank, int64_t timestamp)
18712266Sradhika.jagtap@arm.com{
18812266Sradhika.jagtap@arm.com  printWarningIfPoweredDown("Command issued while in power-down mode.", MemCommand::PREA, timestamp, bank);
18912266Sradhika.jagtap@arm.com  // If command is explicit PREA (precharge all banks) - update
19012266Sradhika.jagtap@arm.com  // number of precharges by the number of active banks, update the bank
19112266Sradhika.jagtap@arm.com  // state of all banks to PRE and set the precharge cycle (the cycle in
19212266Sradhika.jagtap@arm.com  // which the memory state changes from ACT to PRE, aka last_pre_cycle).
19312266Sradhika.jagtap@arm.com  // Calculate the number of active cycles if the memory was in the
19412266Sradhika.jagtap@arm.com  // active state before, but there is a state transition to PRE now.
19512266Sradhika.jagtap@arm.com
19612266Sradhika.jagtap@arm.com  if (nActiveBanks() > 0) {
19712266Sradhika.jagtap@arm.com    // Active banks are being precharged
19812266Sradhika.jagtap@arm.com    // At least one bank was active, therefore the current memory state is
19912266Sradhika.jagtap@arm.com    // ACT. Since all banks are being precharged a memory state transition
20012266Sradhika.jagtap@arm.com    // to PRE is happening. Add to the counter the amount of cycles the
20112266Sradhika.jagtap@arm.com    // memory remained in the ACT state.
20212266Sradhika.jagtap@arm.com
20312266Sradhika.jagtap@arm.com    actcycles += zero_guard(timestamp - first_act_cycle, "first_act_cycle is in the future.");
20412266Sradhika.jagtap@arm.com    last_pre_cycle = timestamp;
20512266Sradhika.jagtap@arm.com
20612266Sradhika.jagtap@arm.com    for (unsigned b = 0; b < num_banks; b++) {
20712266Sradhika.jagtap@arm.com      if (bank_state[b] == BANK_ACTIVE) {
20812266Sradhika.jagtap@arm.com        // Active banks are being precharged
20912266Sradhika.jagtap@arm.com        numberofpresBanks[b] += 1;
21012266Sradhika.jagtap@arm.com        actcyclesBanks[b] += zero_guard(timestamp - first_act_cycle_banks[b], "first_act_cycle is in the future (bank).");
21112266Sradhika.jagtap@arm.com      }
21212266Sradhika.jagtap@arm.com    }
21312266Sradhika.jagtap@arm.com
21412266Sradhika.jagtap@arm.com    idle_act_update(latest_read_cycle, latest_write_cycle, latest_act_cycle, timestamp);
21512266Sradhika.jagtap@arm.com
21612266Sradhika.jagtap@arm.com    latest_pre_cycle = timestamp;
21712266Sradhika.jagtap@arm.com    // Reset the state for all banks to precharged.
21812266Sradhika.jagtap@arm.com    for (auto& bs : bank_state) {
21912266Sradhika.jagtap@arm.com      bs = BANK_PRECHARGED;
22012266Sradhika.jagtap@arm.com    }
22112266Sradhika.jagtap@arm.com  } else {
22212266Sradhika.jagtap@arm.com    printWarning("All banks are already precharged!", MemCommand::PREA, timestamp, bank);
22312266Sradhika.jagtap@arm.com  }
22412266Sradhika.jagtap@arm.com}
22512266Sradhika.jagtap@arm.com
22612266Sradhika.jagtap@arm.comvoid CommandAnalysis::handlePdnFAct(unsigned bank, int64_t timestamp)
22712266Sradhika.jagtap@arm.com{
22812266Sradhika.jagtap@arm.com  // If command is fast-exit active power-down - update number of
22912266Sradhika.jagtap@arm.com  // power-downs, set the power-down cycle and the memory mode to
23012266Sradhika.jagtap@arm.com  // fast-exit active power-down. Save states of all the banks from
23112266Sradhika.jagtap@arm.com  // the cycle before entering active power-down, to be returned to
23212266Sradhika.jagtap@arm.com  // after powering-up. Update active and active idle cycles.
23312266Sradhika.jagtap@arm.com  printWarningIfNotActive("All banks are precharged! Incorrect use of Active Power-Down.", MemCommand::PDN_F_ACT, timestamp, bank);
23412266Sradhika.jagtap@arm.com  f_act_pdns++;
23512266Sradhika.jagtap@arm.com  last_bank_state = bank_state;
23612266Sradhika.jagtap@arm.com  pdn_cycle  = timestamp;
23712266Sradhika.jagtap@arm.com  actcycles += zero_guard(timestamp - first_act_cycle, "first_act_cycle is in the future.");
23812266Sradhika.jagtap@arm.com  for (unsigned b = 0; b < num_banks; b++) {
23912266Sradhika.jagtap@arm.com    if (bank_state[b] == BANK_ACTIVE) {
24012266Sradhika.jagtap@arm.com      actcyclesBanks[b] += zero_guard(timestamp - first_act_cycle_banks[b], "first_act_cycle is in the future (bank).");
24112266Sradhika.jagtap@arm.com    }
24212266Sradhika.jagtap@arm.com  }
24312266Sradhika.jagtap@arm.com  idle_act_update(latest_read_cycle, latest_write_cycle, latest_act_cycle, timestamp);
24412266Sradhika.jagtap@arm.com  mem_state  = CommandAnalysis::MS_PDN_F_ACT;
24512266Sradhika.jagtap@arm.com}
24612266Sradhika.jagtap@arm.com
24712266Sradhika.jagtap@arm.comvoid CommandAnalysis::handlePdnSAct(unsigned bank, int64_t timestamp)
24812266Sradhika.jagtap@arm.com{
24912266Sradhika.jagtap@arm.com  // If command is slow-exit active power-down - update number of
25012266Sradhika.jagtap@arm.com  // power-downs, set the power-down cycle and the memory mode to
25112266Sradhika.jagtap@arm.com  // slow-exit active power-down. Save states of all the banks from
25212266Sradhika.jagtap@arm.com  // the cycle before entering active power-down, to be returned to
25312266Sradhika.jagtap@arm.com  // after powering-up. Update active and active idle cycles.
25412266Sradhika.jagtap@arm.com  printWarningIfNotActive("All banks are precharged! Incorrect use of Active Power-Down.", MemCommand::PDN_S_ACT, timestamp, bank);
25512266Sradhika.jagtap@arm.com  s_act_pdns++;
25612266Sradhika.jagtap@arm.com  last_bank_state = bank_state;
25712266Sradhika.jagtap@arm.com  pdn_cycle  = timestamp;
25812266Sradhika.jagtap@arm.com  actcycles += zero_guard(timestamp - first_act_cycle, "first_act_cycle is in the future.");
25912266Sradhika.jagtap@arm.com  for (unsigned b = 0; b < num_banks; b++) {
26012266Sradhika.jagtap@arm.com    if (bank_state[b] == BANK_ACTIVE) {
26112266Sradhika.jagtap@arm.com      actcyclesBanks[b] += zero_guard(timestamp - first_act_cycle_banks[b], "first_act_cycle is in the future (bank).");
26212266Sradhika.jagtap@arm.com    }
26312266Sradhika.jagtap@arm.com  }
26412266Sradhika.jagtap@arm.com  idle_act_update(latest_read_cycle, latest_write_cycle, latest_act_cycle, timestamp);
26512266Sradhika.jagtap@arm.com  mem_state  = CommandAnalysis::MS_PDN_S_ACT;
26612266Sradhika.jagtap@arm.com}
26712266Sradhika.jagtap@arm.com
26812266Sradhika.jagtap@arm.comvoid CommandAnalysis::handlePdnFPre(unsigned bank, int64_t timestamp)
26912266Sradhika.jagtap@arm.com{
27012266Sradhika.jagtap@arm.com  // If command is fast-exit precharged power-down - update number of
27112266Sradhika.jagtap@arm.com  // power-downs, set the power-down cycle and the memory mode to
27212266Sradhika.jagtap@arm.com  // fast-exit precahrged power-down. Update precharged and precharged
27312266Sradhika.jagtap@arm.com  // idle cycles.
27412266Sradhika.jagtap@arm.com  printWarningIfActive("One or more banks are active! Incorrect use of Precharged Power-Down.", MemCommand::PDN_F_PRE, timestamp, bank);
27512266Sradhika.jagtap@arm.com  f_pre_pdns++;
27612266Sradhika.jagtap@arm.com  pdn_cycle  = timestamp;
27712266Sradhika.jagtap@arm.com  precycles += zero_guard(timestamp - last_pre_cycle, "3 last_pre_cycle is in the future.");
27812266Sradhika.jagtap@arm.com  idle_pre_update(timestamp, latest_pre_cycle);
27912266Sradhika.jagtap@arm.com  mem_state  = CommandAnalysis::MS_PDN_F_PRE;
28012266Sradhika.jagtap@arm.com}
28112266Sradhika.jagtap@arm.com
28212266Sradhika.jagtap@arm.comvoid CommandAnalysis::handlePdnSPre(unsigned bank, int64_t timestamp)
28312266Sradhika.jagtap@arm.com{
28412266Sradhika.jagtap@arm.com  // If command is slow-exit precharged power-down - update number of
28512266Sradhika.jagtap@arm.com  // power-downs, set the power-down cycle and the memory mode to
28612266Sradhika.jagtap@arm.com  // slow-exit precahrged power-down. Update precharged and precharged
28712266Sradhika.jagtap@arm.com  // idle cycles.
28812266Sradhika.jagtap@arm.com  printWarningIfActive("One or more banks are active! Incorrect use of Precharged Power-Down.",  MemCommand::PDN_S_PRE, timestamp, bank);
28912266Sradhika.jagtap@arm.com  s_pre_pdns++;
29012266Sradhika.jagtap@arm.com  pdn_cycle  = timestamp;
29112266Sradhika.jagtap@arm.com  precycles += zero_guard(timestamp - last_pre_cycle, "4 last_pre_cycle is in the future.");
29212266Sradhika.jagtap@arm.com  idle_pre_update(timestamp, latest_pre_cycle);
29312266Sradhika.jagtap@arm.com  mem_state  = CommandAnalysis::MS_PDN_S_PRE;
29412266Sradhika.jagtap@arm.com}
29512266Sradhika.jagtap@arm.com
29612266Sradhika.jagtap@arm.comvoid CommandAnalysis::handlePupAct(int64_t timestamp)
29712266Sradhika.jagtap@arm.com{
29812266Sradhika.jagtap@arm.com  // If command is power-up in the active mode - check the power-down
29912266Sradhika.jagtap@arm.com  // exit-mode employed (fast or slow), update the number of power-down
30012266Sradhika.jagtap@arm.com  // and power-up cycles and the latest and first act cycle. Also, reset
30112266Sradhika.jagtap@arm.com  // all the individual bank states to the respective saved states
30212266Sradhika.jagtap@arm.com  // before entering power-down.
30312266Sradhika.jagtap@arm.com  const MemTimingSpec& t = memSpec.memTimingSpec;
30412266Sradhika.jagtap@arm.com
30512266Sradhika.jagtap@arm.com  if (mem_state == CommandAnalysis::MS_PDN_F_ACT) {
30612266Sradhika.jagtap@arm.com    f_act_pdcycles  += zero_guard(timestamp - pdn_cycle, "pdn_cycle is in the future.");
30712266Sradhika.jagtap@arm.com    pup_act_cycles  += t.XP;
30812266Sradhika.jagtap@arm.com    latest_act_cycle = timestamp;
30912266Sradhika.jagtap@arm.com  } else if (mem_state == CommandAnalysis::MS_PDN_S_ACT) {
31012266Sradhika.jagtap@arm.com    s_act_pdcycles += zero_guard(timestamp - pdn_cycle, "pdn_cycle is in the future.");
31112266Sradhika.jagtap@arm.com    if (memSpec.memArchSpec.dll == false) {
31212266Sradhika.jagtap@arm.com      pup_act_cycles  += t.XP;
31312266Sradhika.jagtap@arm.com      latest_act_cycle = timestamp;
31412266Sradhika.jagtap@arm.com    } else {
31512266Sradhika.jagtap@arm.com      pup_act_cycles  += t.XPDLL - t.RCD;
31612266Sradhika.jagtap@arm.com      latest_act_cycle = timestamp + zero_guard(t.XPDLL - (2 * t.RCD), "t.XPDLL - (2 * t.RCD) < 0");
31712266Sradhika.jagtap@arm.com    }
31812266Sradhika.jagtap@arm.com  } else {
31912266Sradhika.jagtap@arm.com    cerr << "Incorrect use of Active Power-Up!" << endl;
32012266Sradhika.jagtap@arm.com  }
32112266Sradhika.jagtap@arm.com  mem_state = MS_NOT_IN_PD;
32212266Sradhika.jagtap@arm.com  bank_state = last_bank_state;
32312266Sradhika.jagtap@arm.com  first_act_cycle = timestamp;
32412266Sradhika.jagtap@arm.com  std::fill(first_act_cycle_banks.begin(), first_act_cycle_banks.end(), timestamp);
32512266Sradhika.jagtap@arm.com}
32612266Sradhika.jagtap@arm.com
32712266Sradhika.jagtap@arm.comvoid CommandAnalysis::handlePupPre(int64_t timestamp)
32812266Sradhika.jagtap@arm.com{
32912266Sradhika.jagtap@arm.com  // If command is power-up in the precharged mode - check the power-down
33012266Sradhika.jagtap@arm.com  // exit-mode employed (fast or slow), update the number of power-down
33112266Sradhika.jagtap@arm.com  // and power-up cycles and the latest and last pre cycle.
33212266Sradhika.jagtap@arm.com  const MemTimingSpec& t = memSpec.memTimingSpec;
33312266Sradhika.jagtap@arm.com  if (mem_state == CommandAnalysis::MS_PDN_F_PRE) {
33412266Sradhika.jagtap@arm.com    f_pre_pdcycles  += zero_guard(timestamp - pdn_cycle, "pdn_cycle is in the future.");
33512266Sradhika.jagtap@arm.com    pup_pre_cycles  += t.XP;
33612266Sradhika.jagtap@arm.com    latest_pre_cycle = timestamp;
33712266Sradhika.jagtap@arm.com  } else if (mem_state == CommandAnalysis::MS_PDN_S_PRE) {
33812266Sradhika.jagtap@arm.com    s_pre_pdcycles += zero_guard(timestamp - pdn_cycle, "pdn_cycle is in the future.");
33912266Sradhika.jagtap@arm.com    if (memSpec.memArchSpec.dll == false) {
34012266Sradhika.jagtap@arm.com      pup_pre_cycles  += t.XP;
34112266Sradhika.jagtap@arm.com      latest_pre_cycle = timestamp;
34212266Sradhika.jagtap@arm.com    } else {
34312266Sradhika.jagtap@arm.com      pup_pre_cycles  += t.XPDLL - t.RCD;
34412266Sradhika.jagtap@arm.com      latest_pre_cycle = timestamp + zero_guard(t.XPDLL - t.RCD - t.RP, "t.XPDLL - t.RCD - t.RP");
34512266Sradhika.jagtap@arm.com    }
34612266Sradhika.jagtap@arm.com  } else {
34712266Sradhika.jagtap@arm.com    cerr << "Incorrect use of Precharged Power-Up!" << endl;
34812266Sradhika.jagtap@arm.com  }
34912266Sradhika.jagtap@arm.com  mem_state      = MS_NOT_IN_PD;
35012266Sradhika.jagtap@arm.com  last_pre_cycle = timestamp;
35112266Sradhika.jagtap@arm.com}
35212266Sradhika.jagtap@arm.com
35312266Sradhika.jagtap@arm.comvoid CommandAnalysis::handleSREn(unsigned bank, int64_t timestamp)
35412266Sradhika.jagtap@arm.com{
35512266Sradhika.jagtap@arm.com  // If command is self-refresh - update number of self-refreshes,
35612266Sradhika.jagtap@arm.com  // set memory state to SREF, update precharge and idle precharge
35712266Sradhika.jagtap@arm.com  // cycles and set the self-refresh cycle.
35812266Sradhika.jagtap@arm.com  printWarningIfActive("One or more banks are active! SREF requires all banks to be precharged.", MemCommand::SREN, timestamp, bank);
35912266Sradhika.jagtap@arm.com  numberofsrefs++;
36012266Sradhika.jagtap@arm.com  sref_cycle = timestamp;
36112266Sradhika.jagtap@arm.com  sref_cycle_window = timestamp;
36212266Sradhika.jagtap@arm.com  sref_ref_pre_cycles_window = 0;
36312266Sradhika.jagtap@arm.com  sref_ref_act_cycles_window = 0;
36412266Sradhika.jagtap@arm.com  precycles += zero_guard(timestamp - last_pre_cycle, "5  last_pre_cycle is in the future.");
36512266Sradhika.jagtap@arm.com  idle_pre_update(timestamp, latest_pre_cycle);
36612266Sradhika.jagtap@arm.com  mem_state  = CommandAnalysis::MS_SREF;
36712266Sradhika.jagtap@arm.com}
36812266Sradhika.jagtap@arm.com
36912266Sradhika.jagtap@arm.comvoid CommandAnalysis::handleSREx(unsigned bank, int64_t timestamp)
37012266Sradhika.jagtap@arm.com{
37112266Sradhika.jagtap@arm.com  // If command is self-refresh exit - update the number of self-refresh
37212266Sradhika.jagtap@arm.com  // clock cycles, number of active and precharged auto-refresh clock
37312266Sradhika.jagtap@arm.com  // cycles during self-refresh and self-refresh exit based on the number
37412266Sradhika.jagtap@arm.com  // of cycles in the self-refresh mode and auto-refresh duration (RFC).
37512266Sradhika.jagtap@arm.com  // Set the last and latest precharge cycle accordingly and set the
37612266Sradhika.jagtap@arm.com  // memory state to 0.
37712266Sradhika.jagtap@arm.com  const MemTimingSpec& t = memSpec.memTimingSpec;
37812266Sradhika.jagtap@arm.com  if (mem_state != CommandAnalysis::MS_SREF) {
37912266Sradhika.jagtap@arm.com    cerr << "Incorrect use of Self-Refresh Power-Up!" << endl;
38012266Sradhika.jagtap@arm.com  }
38112266Sradhika.jagtap@arm.com  // The total duration of self-refresh is given by the difference between
38212266Sradhika.jagtap@arm.com  // the current clock cycle and the clock cycle of entering self-refresh.
38312266Sradhika.jagtap@arm.com  int64_t sref_duration = timestamp - sref_cycle;
38412266Sradhika.jagtap@arm.com
38512266Sradhika.jagtap@arm.com  // Negative or zero duration should never happen.
38612266Sradhika.jagtap@arm.com  if (sref_duration <= 0) {
38712266Sradhika.jagtap@arm.com    printWarning("Invalid Self-Refresh duration!", MemCommand::SREX, timestamp, bank);
38812266Sradhika.jagtap@arm.com    sref_duration = 0;
38912266Sradhika.jagtap@arm.com  }
39012266Sradhika.jagtap@arm.com
39112266Sradhika.jagtap@arm.com  // The minimum time that the DRAM must remain in Self-Refresh is CKESR.
39212266Sradhika.jagtap@arm.com  if (sref_duration < t.CKESR) {
39312266Sradhika.jagtap@arm.com    printWarning("Self-Refresh duration < CKESR!", MemCommand::SREX, timestamp, bank);
39412266Sradhika.jagtap@arm.com  }
39512266Sradhika.jagtap@arm.com
39612266Sradhika.jagtap@arm.com  if (sref_duration >= t.RFC) {
39712266Sradhika.jagtap@arm.com    /*
39812266Sradhika.jagtap@arm.com     * Self-refresh Exit Context 1 (tSREF >= tRFC):
39912266Sradhika.jagtap@arm.com     * The memory remained in self-refresh for a certain number of clock
40012266Sradhika.jagtap@arm.com     * cycles greater than a refresh cycle time (RFC). Consequently, the
40112266Sradhika.jagtap@arm.com     * initial auto-refresh accomplished.
40212266Sradhika.jagtap@arm.com     *
40312266Sradhika.jagtap@arm.com     *
40412266Sradhika.jagtap@arm.com     *  SREN                                #              SREX
40512266Sradhika.jagtap@arm.com     *  |                                   #                ^
40612266Sradhika.jagtap@arm.com     *  |                                   #                |
40712266Sradhika.jagtap@arm.com     *  |<------------------------- tSREF ----------...----->|
40812266Sradhika.jagtap@arm.com     *  |                                   #                |
40912266Sradhika.jagtap@arm.com     *  |      Initial Auto-Refresh         #                |
41012266Sradhika.jagtap@arm.com     *  v                                   #                |
41112266Sradhika.jagtap@arm.com     *  ------------------------------------#-------...-----------------> t
41212266Sradhika.jagtap@arm.com     *                                      #
41312266Sradhika.jagtap@arm.com     *   <------------- tRFC -------------->#
41412266Sradhika.jagtap@arm.com     *   <---- (tRFC - tRP) ----><-- tRP -->#
41512266Sradhika.jagtap@arm.com     *               |                |
41612266Sradhika.jagtap@arm.com     *               v                v
41712266Sradhika.jagtap@arm.com     *     sref_ref_act_cycles     sref_ref_pre_cycles
41812266Sradhika.jagtap@arm.com     *
41912266Sradhika.jagtap@arm.com     *
42012266Sradhika.jagtap@arm.com     * Summary:
42112266Sradhika.jagtap@arm.com     * sref_cycles += tSREF – tRFC
42212266Sradhika.jagtap@arm.com     * sref_ref_act_cycles += tRFC - tRP
42312266Sradhika.jagtap@arm.com     * sref_ref_pre_cycles += tRP
42412266Sradhika.jagtap@arm.com     * spup_ref_act_cycles += 0
42512266Sradhika.jagtap@arm.com     * spup_ref_pre_cycles += 0
42612266Sradhika.jagtap@arm.com     *
42712266Sradhika.jagtap@arm.com     */
42812266Sradhika.jagtap@arm.com
42912266Sradhika.jagtap@arm.com    // The initial auto-refresh consumes (IDD5 − IDD3N) over one refresh
43012266Sradhika.jagtap@arm.com    // period (RFC) from the start of the self-refresh.
43112266Sradhika.jagtap@arm.com    sref_ref_act_cycles += t.RFC -
43212266Sradhika.jagtap@arm.com                           t.RP - sref_ref_act_cycles_window;
43312266Sradhika.jagtap@arm.com    sref_ref_pre_cycles += t.RP - sref_ref_pre_cycles_window;
43412266Sradhika.jagtap@arm.com    last_pre_cycle       = timestamp;
43512266Sradhika.jagtap@arm.com
43612266Sradhika.jagtap@arm.com    // The IDD6 current is consumed for the time period spent in the
43712266Sradhika.jagtap@arm.com    // self-refresh mode, which excludes the time spent in finishing the
43812266Sradhika.jagtap@arm.com    // initial auto-refresh.
43912266Sradhika.jagtap@arm.com    if (sref_cycle_window > sref_cycle + t.RFC) {
44012266Sradhika.jagtap@arm.com        sref_cycles += zero_guard(timestamp - sref_cycle_window, "sref_cycle_window is in the future.");
44112266Sradhika.jagtap@arm.com    } else {
44212266Sradhika.jagtap@arm.com        sref_cycles += zero_guard(timestamp - sref_cycle - t.RFC, "sref_cycle - t.RFC < 0");
44312266Sradhika.jagtap@arm.com    }
44412266Sradhika.jagtap@arm.com
44512266Sradhika.jagtap@arm.com    // IDD2N current is consumed when exiting the self-refresh state.
44612266Sradhika.jagtap@arm.com    if (memSpec.memArchSpec.dll == false) {
44712266Sradhika.jagtap@arm.com      spup_cycles     += t.XS;
44812266Sradhika.jagtap@arm.com      latest_pre_cycle = timestamp + zero_guard(t.XS - t.RP, "t.XS - t.RP < 0");
44912266Sradhika.jagtap@arm.com    } else {
45012266Sradhika.jagtap@arm.com      spup_cycles     += t.XSDLL - t.RCD;
45112266Sradhika.jagtap@arm.com      latest_pre_cycle = timestamp + zero_guard(t.XSDLL - t.RCD  - t.RP, "t.XSDLL - t.RCD  - t.RP < 0");
45212266Sradhika.jagtap@arm.com    }
45312266Sradhika.jagtap@arm.com
45412266Sradhika.jagtap@arm.com  } else {
45512266Sradhika.jagtap@arm.com    // Self-refresh Exit Context 2 (tSREF < tRFC):
45612266Sradhika.jagtap@arm.com    // Exit self-refresh before the completion of the initial
45712266Sradhika.jagtap@arm.com    // auto-refresh.
45812266Sradhika.jagtap@arm.com
45912266Sradhika.jagtap@arm.com    // Number of active cycles needed by an auto-refresh.
46012266Sradhika.jagtap@arm.com    int64_t ref_act_cycles = t.RFC - t.RP;
46112266Sradhika.jagtap@arm.com
46212266Sradhika.jagtap@arm.com    if (sref_duration >= ref_act_cycles) {
46312266Sradhika.jagtap@arm.com      /*
46412266Sradhika.jagtap@arm.com       * Self-refresh Exit Context 2A (tSREF < tRFC && tSREF >= tRFC - tRP):
46512266Sradhika.jagtap@arm.com       * The duration of self-refresh is equal or greater than the number
46612266Sradhika.jagtap@arm.com       * of active cycles needed by the initial auto-refresh.
46712266Sradhika.jagtap@arm.com       *
46812266Sradhika.jagtap@arm.com       *
46912266Sradhika.jagtap@arm.com       *  SREN                                           SREX
47012266Sradhika.jagtap@arm.com       *  |                                                ^         #
47112266Sradhika.jagtap@arm.com       *  |                                                |         #
47212266Sradhika.jagtap@arm.com       *  |<------------------ tSREF --------------------->|         #
47312266Sradhika.jagtap@arm.com       *  |                                                |         #
47412266Sradhika.jagtap@arm.com       *  |                                  Initial Auto-Refresh    #
47512266Sradhika.jagtap@arm.com       *  v                                                |         #
47612266Sradhika.jagtap@arm.com       *  -----------------------------------------------------------#--> t
47712266Sradhika.jagtap@arm.com       *                                                             #
47812266Sradhika.jagtap@arm.com       *   <------------------------ tRFC -------------------------->#
47912266Sradhika.jagtap@arm.com       *   <------------- (tRFC - tRP)--------------><----- tRP ---->#
48012266Sradhika.jagtap@arm.com       *           |                                 <-----><------->
48112266Sradhika.jagtap@arm.com       *           v                                  |         |
48212266Sradhika.jagtap@arm.com       *     sref_ref_act_cycles                      v         v
48312266Sradhika.jagtap@arm.com       *                             sref_ref_pre_cycles spup_ref_pre_cycles
48412266Sradhika.jagtap@arm.com       *
48512266Sradhika.jagtap@arm.com       *
48612266Sradhika.jagtap@arm.com       * Summary:
48712266Sradhika.jagtap@arm.com       * sref_cycles += 0
48812266Sradhika.jagtap@arm.com       * sref_ref_act_cycles += tRFC - tRP
48912266Sradhika.jagtap@arm.com       * sref_ref_pre_cycles += tSREF – (tRFC – tRP)
49012266Sradhika.jagtap@arm.com       * spup_ref_act_cycles += 0
49112266Sradhika.jagtap@arm.com       * spup_ref_pre_cycles += tRP – sref_ref_pre_cycles
49212266Sradhika.jagtap@arm.com       *
49312266Sradhika.jagtap@arm.com       */
49412266Sradhika.jagtap@arm.com
49512266Sradhika.jagtap@arm.com      // Number of precharged cycles (zero <= pre_cycles < RP)
49612266Sradhika.jagtap@arm.com      int64_t pre_cycles = sref_duration - ref_act_cycles - sref_ref_pre_cycles_window;
49712266Sradhika.jagtap@arm.com
49812266Sradhika.jagtap@arm.com      sref_ref_act_cycles += ref_act_cycles - sref_ref_act_cycles_window;
49912266Sradhika.jagtap@arm.com      sref_ref_pre_cycles += pre_cycles;
50012266Sradhika.jagtap@arm.com
50112266Sradhika.jagtap@arm.com      // Number of precharged cycles during the self-refresh power-up. It
50212266Sradhika.jagtap@arm.com      // is at maximum tRP (if pre_cycles is zero).
50312266Sradhika.jagtap@arm.com      int64_t spup_pre = t.RP - pre_cycles;
50412266Sradhika.jagtap@arm.com
50512266Sradhika.jagtap@arm.com      spup_ref_pre_cycles += spup_pre;
50612266Sradhika.jagtap@arm.com
50712266Sradhika.jagtap@arm.com      last_pre_cycle       = timestamp + spup_pre;
50812266Sradhika.jagtap@arm.com
50912266Sradhika.jagtap@arm.com      if (memSpec.memArchSpec.dll == false) {
51012266Sradhika.jagtap@arm.com        spup_cycles     += t.XS - spup_pre;
51112266Sradhika.jagtap@arm.com        latest_pre_cycle = timestamp + zero_guard(t.XS - spup_pre - t.RP, "t.XS - spup_pre - t.RP < 0");
51212266Sradhika.jagtap@arm.com      } else {
51312266Sradhika.jagtap@arm.com        spup_cycles     += t.XSDLL - t.RCD - spup_pre;
51412266Sradhika.jagtap@arm.com        latest_pre_cycle = timestamp + zero_guard(t.XSDLL - t.RCD - spup_pre - t.RP, "t.XSDLL - t.RCD - spup_pre - t.RP");
51512266Sradhika.jagtap@arm.com      }
51612266Sradhika.jagtap@arm.com    } else {
51712266Sradhika.jagtap@arm.com      /*
51812266Sradhika.jagtap@arm.com       * Self-refresh Exit Context 2B (tSREF < tRFC - tRP):
51912266Sradhika.jagtap@arm.com       * self-refresh duration is shorter than the number of active cycles
52012266Sradhika.jagtap@arm.com       * needed by the initial auto-refresh.
52112266Sradhika.jagtap@arm.com       *
52212266Sradhika.jagtap@arm.com       *
52312266Sradhika.jagtap@arm.com       *  SREN                             SREX
52412266Sradhika.jagtap@arm.com       *  |                                  ^                        #
52512266Sradhika.jagtap@arm.com       *  |                                  |                        #
52612266Sradhika.jagtap@arm.com       *  |<-------------- tSREF ----------->|                        #
52712266Sradhika.jagtap@arm.com       *  |                                  |                        #
52812266Sradhika.jagtap@arm.com       *  |                       Initial Auto-Refresh                #
52912266Sradhika.jagtap@arm.com       *  v                                  |                        #
53012266Sradhika.jagtap@arm.com       *  ------------------------------------------------------------#--> t
53112266Sradhika.jagtap@arm.com       *                                                              #
53212266Sradhika.jagtap@arm.com       *   <------------------------ tRFC --------------------------->#
53312266Sradhika.jagtap@arm.com       *   <-------------- (tRFC - tRP)-------------><------ tRP ---->#
53412266Sradhika.jagtap@arm.com       *   <--------------------------------><------><--------------->
53512266Sradhika.jagtap@arm.com       *               |                        |             |
53612266Sradhika.jagtap@arm.com       *               v                        v             v
53712266Sradhika.jagtap@arm.com       *     sref_ref_act_cycles    spup_ref_act_cycles spup_ref_pre_cycles
53812266Sradhika.jagtap@arm.com       *
53912266Sradhika.jagtap@arm.com       *
54012266Sradhika.jagtap@arm.com       * Summary:
54112266Sradhika.jagtap@arm.com       * sref_cycles += 0
54212266Sradhika.jagtap@arm.com       * sref_ref_act_cycles += tSREF
54312266Sradhika.jagtap@arm.com       * sref_ref_pre_cycles += 0
54412266Sradhika.jagtap@arm.com       * spup_ref_act_cycles += (tRFC – tRP) - tSREF
54512266Sradhika.jagtap@arm.com       * spup_ref_pre_cycles += tRP
54612266Sradhika.jagtap@arm.com       *
54712266Sradhika.jagtap@arm.com       */
54812266Sradhika.jagtap@arm.com
54912266Sradhika.jagtap@arm.com      sref_ref_act_cycles += sref_duration - sref_ref_act_cycles_window;
55012266Sradhika.jagtap@arm.com
55112266Sradhika.jagtap@arm.com      int64_t spup_act = (t.RFC - t.RP) - sref_duration;
55212266Sradhika.jagtap@arm.com
55312266Sradhika.jagtap@arm.com      spup_ref_act_cycles += spup_act;
55412266Sradhika.jagtap@arm.com      spup_ref_pre_cycles += t.RP;
55512266Sradhika.jagtap@arm.com
55612266Sradhika.jagtap@arm.com      last_pre_cycle       = timestamp + spup_act + t.RP;
55712266Sradhika.jagtap@arm.com      if (memSpec.memArchSpec.dll == false) {
55812266Sradhika.jagtap@arm.com        spup_cycles     += t.XS - spup_act - t.RP;
55912266Sradhika.jagtap@arm.com        latest_pre_cycle = timestamp + zero_guard(t.XS - spup_act - (2 * t.RP), "t.XS - spup_act - (2 * t.RP) < 0");
56012266Sradhika.jagtap@arm.com      } else {
56112266Sradhika.jagtap@arm.com        spup_cycles     += t.XSDLL - t.RCD - spup_act - t.RP;
56212266Sradhika.jagtap@arm.com        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");
56312266Sradhika.jagtap@arm.com      }
56412266Sradhika.jagtap@arm.com    }
56512266Sradhika.jagtap@arm.com  }
56612266Sradhika.jagtap@arm.com  mem_state = MS_NOT_IN_PD;
56712266Sradhika.jagtap@arm.com}
56812266Sradhika.jagtap@arm.com
56912266Sradhika.jagtap@arm.com
57012266Sradhika.jagtap@arm.comvoid CommandAnalysis::handleNopEnd(int64_t timestamp)
57112266Sradhika.jagtap@arm.com{
57212266Sradhika.jagtap@arm.com  // May be optionally used at the end of memory trace for better accuracy
57312266Sradhika.jagtap@arm.com  // Update all counters based on completion of operations.
57412266Sradhika.jagtap@arm.com  const MemTimingSpec& t = memSpec.memTimingSpec;
57512266Sradhika.jagtap@arm.com  for (unsigned b = 0; b < num_banks; b++) {
57612266Sradhika.jagtap@arm.com    if (bank_state[b] == BANK_ACTIVE) {
57712266Sradhika.jagtap@arm.com      actcyclesBanks[b] += zero_guard(timestamp - first_act_cycle_banks[b], "first_act_cycle is in the future (bank)");
57812266Sradhika.jagtap@arm.com    }
57912266Sradhika.jagtap@arm.com  }
58012266Sradhika.jagtap@arm.com
58112266Sradhika.jagtap@arm.com  if (nActiveBanks() > 0 && mem_state == MS_NOT_IN_PD) {
58212266Sradhika.jagtap@arm.com    actcycles += zero_guard(timestamp - first_act_cycle, "first_act_cycle is in the future");
58312266Sradhika.jagtap@arm.com    idle_act_update(latest_read_cycle, latest_write_cycle,
58412266Sradhika.jagtap@arm.com                    latest_act_cycle, timestamp);
58512266Sradhika.jagtap@arm.com  } else if (nActiveBanks() == 0 && mem_state == MS_NOT_IN_PD) {
58612266Sradhika.jagtap@arm.com    precycles += zero_guard(timestamp - last_pre_cycle, "6 last_pre_cycle is in the future");
58712266Sradhika.jagtap@arm.com    idle_pre_update(timestamp, latest_pre_cycle);
58812266Sradhika.jagtap@arm.com  } else if (mem_state == CommandAnalysis::MS_PDN_F_ACT) {
58912266Sradhika.jagtap@arm.com    f_act_pdcycles += zero_guard(timestamp - pdn_cycle, "pdn_cycle is in the future");
59012266Sradhika.jagtap@arm.com  } else if (mem_state == CommandAnalysis::MS_PDN_S_ACT) {
59112266Sradhika.jagtap@arm.com    s_act_pdcycles += zero_guard(timestamp - pdn_cycle, "pdn_cycle is in the future");
59212266Sradhika.jagtap@arm.com  } else if (mem_state == CommandAnalysis::MS_PDN_F_PRE) {
59312266Sradhika.jagtap@arm.com    f_pre_pdcycles += zero_guard(timestamp - pdn_cycle, "pdn_cycle is in the future");
59412266Sradhika.jagtap@arm.com  } else if (mem_state == CommandAnalysis::MS_PDN_S_PRE) {
59512266Sradhika.jagtap@arm.com    s_pre_pdcycles += zero_guard(timestamp - pdn_cycle, "pdn_cycle is in the future");
59612266Sradhika.jagtap@arm.com  } else if (mem_state == CommandAnalysis::MS_SREF) {
59712266Sradhika.jagtap@arm.com    auto rfc_minus_rp = (t.RFC - t.RP);
59812266Sradhika.jagtap@arm.com
59912266Sradhika.jagtap@arm.com    if (timestamp > sref_cycle + t.RFC) {
60012266Sradhika.jagtap@arm.com      if (sref_cycle_window <= sref_cycle + rfc_minus_rp) {
60112266Sradhika.jagtap@arm.com        sref_ref_act_cycles += rfc_minus_rp - sref_ref_act_cycles_window;
60212266Sradhika.jagtap@arm.com        sref_ref_act_cycles_window = rfc_minus_rp;
60312266Sradhika.jagtap@arm.com        sref_cycle_window = sref_cycle + rfc_minus_rp;
60412266Sradhika.jagtap@arm.com      }
60512266Sradhika.jagtap@arm.com      if (sref_cycle_window <= sref_cycle + t.RFC) {
60612266Sradhika.jagtap@arm.com        sref_ref_pre_cycles += t.RP - sref_ref_pre_cycles_window;
60712266Sradhika.jagtap@arm.com        sref_ref_pre_cycles_window = t.RP;
60812266Sradhika.jagtap@arm.com        sref_cycle_window = sref_cycle + t.RFC;
60912266Sradhika.jagtap@arm.com      }
61012266Sradhika.jagtap@arm.com      sref_cycles += zero_guard(timestamp - sref_cycle_window, "sref_cycle_window is in the future");
61112266Sradhika.jagtap@arm.com    } else if (timestamp > sref_cycle + rfc_minus_rp) {
61212266Sradhika.jagtap@arm.com
61312266Sradhika.jagtap@arm.com      if (sref_cycle_window <= sref_cycle + rfc_minus_rp) {
61412266Sradhika.jagtap@arm.com        sref_ref_act_cycles += rfc_minus_rp - sref_ref_act_cycles_window;
61512266Sradhika.jagtap@arm.com        sref_ref_act_cycles_window = rfc_minus_rp;
61612266Sradhika.jagtap@arm.com        sref_cycle_window = sref_cycle + rfc_minus_rp;
61712266Sradhika.jagtap@arm.com      }
61812266Sradhika.jagtap@arm.com      sref_ref_pre_cycles_window += timestamp - sref_cycle_window;
61912266Sradhika.jagtap@arm.com      sref_ref_pre_cycles += timestamp - sref_cycle_window;
62012266Sradhika.jagtap@arm.com    } else {
62112266Sradhika.jagtap@arm.com      sref_ref_act_cycles_window += timestamp - sref_cycle_window;
62212266Sradhika.jagtap@arm.com      sref_ref_act_cycles += timestamp - sref_cycle_window;
62312266Sradhika.jagtap@arm.com    }
62412266Sradhika.jagtap@arm.com  }
62512266Sradhika.jagtap@arm.com}
626