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