stats: update stats for mmap() change.
[gem5.git] / ext / drampower / src / CommandAnalysis.cc
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
45 using namespace Data;
46 using namespace std;
47
48 CommandAnalysis::CommandAnalysis()
49 {
50 }
51
52 CommandAnalysis::CommandAnalysis(const int nbrofBanks)
53 {
54 // Initializing all counters and variables
55
56 numberofacts = 0;
57 numberofpres = 0;
58 numberofreads = 0;
59 numberofwrites = 0;
60 numberofrefs = 0;
61 f_act_pdns = 0;
62 s_act_pdns = 0;
63 f_pre_pdns = 0;
64 s_pre_pdns = 0;
65 numberofsrefs = 0;
66
67 pop = 0;
68 init = 0;
69 zero = 0;
70
71 actcycles = 0;
72 precycles = 0;
73 f_act_pdcycles = 0;
74 s_act_pdcycles = 0;
75 f_pre_pdcycles = 0;
76 s_pre_pdcycles = 0;
77 pup_act_cycles = 0;
78 pup_pre_cycles = 0;
79 sref_cycles = 0;
80 spup_cycles = 0;
81 sref_ref_act_cycles = 0;
82 sref_ref_pre_cycles = 0;
83 spup_ref_act_cycles = 0;
84 spup_ref_pre_cycles = 0;
85 idlecycles_act = 0;
86 idlecycles_pre = 0;
87
88 latest_act_cycle = -1;
89 latest_pre_cycle = -1;
90 latest_read_cycle = -1;
91 latest_write_cycle = -1;
92 end_read_op = 0;
93 end_write_op = 0;
94 end_act_op = 0;
95
96 first_act_cycle = 0;
97 last_pre_cycle = 0;
98
99 bankstate.resize(nbrofBanks, 0);
100 last_states.resize(nbrofBanks);
101 mem_state = 0;
102
103 sref_cycle = 0;
104 pdn_cycle = 0;
105
106 cmd_list.clear();
107 full_cmd_list.resize(1, MemCommand::PRE);
108 cached_cmd.clear();
109 activation_cycle.resize(nbrofBanks, 0);
110 }
111
112 // function to clear all arrays
113 void CommandAnalysis::clear()
114 {
115 cached_cmd.clear();
116 cmd_list.clear();
117 full_cmd_list.clear();
118 last_states.clear();
119 bankstate.clear();
120 }
121
122 // Reads through the trace file, identifies the timestamp, command and bank
123 // If the issued command includes an auto-precharge, adds an explicit
124 // precharge to a cached command list and computes the precharge offset from the
125 // issued command timestamp, when the auto-precharge would kick in
126
127 void CommandAnalysis::getCommands(const Data::MemorySpecification& memSpec,
128 const int nbrofBanks, std::vector<MemCommand>& list, bool lastupdate)
129 {
130 for (vector<MemCommand>::const_iterator i = list.begin(); i != list.end(); ++i) {
131 const MemCommand& cmd = *i;
132 cmd_list.push_back(cmd);
133
134 MemCommand::cmds cmdType = cmd.getType();
135 if (cmdType == MemCommand::ACT) {
136 activation_cycle[cmd.getBank()] = cmd.getTimeInt64();
137 } else if (cmdType == MemCommand::RDA || cmdType == MemCommand::WRA) {
138 // Remove auto-precharge flag from command
139 cmd_list.back().setType(cmd.typeWithoutAutoPrechargeFlag());
140
141 // Add the auto precharge to the list of cached_cmds
142 int64_t preTime = max(cmd.getTimeInt64() + cmd.getPrechargeOffset(memSpec, cmdType),
143 activation_cycle[cmd.getBank()] + memSpec.memTimingSpec.RAS);
144 cached_cmd.push_back(MemCommand(MemCommand::PRE, cmd.getBank(), static_cast<double>(preTime)));
145 }
146 }
147 pop = 0;
148 // Note: the extra pre-cmds at the end of the lists, and the cast to double
149 // of the size vector is probably not desirable.
150 cmd_list.push_back(MemCommand::PRE);
151 cached_cmd.push_back(MemCommand::PRE);
152 analyse_commands(nbrofBanks, memSpec, cmd_list.size()-1,
153 cached_cmd.size()-1, lastupdate);
154 cmd_list.clear();
155 cached_cmd.clear();
156 } // CommandAnalysis::getCommands
157
158 // Checks the auto-precharge cached command list and inserts the explicit
159 // precharges with the appropriate timestamp in the original command list
160 // (by merging) based on their offset from the issuing command. Calls the
161 // evaluate function to analyse this expanded list of commands.
162
163 void CommandAnalysis::analyse_commands(const int nbrofBanks,
164 Data::MemorySpecification memSpec, int64_t nCommands, int64_t nCached, bool lastupdate)
165 {
166 full_cmd_list.resize(1, MemCommand::PRE);
167 unsigned mCommands = 0;
168 unsigned mCached = 0;
169 for (unsigned i = 0; i < nCommands + nCached + 1; i++) {
170 if (cached_cmd.size() > 1) {
171 if ((cmd_list[mCommands].getTime() > 1) && (init == 0)) {
172 full_cmd_list[i].setType(MemCommand::PREA);
173 init = 1;
174 pop = 1;
175 } else {
176 init = 1;
177 if ((cached_cmd[mCached].getTime() > 0) && (cmd_list.
178 at(mCommands).getTime() < cached_cmd[mCached].
179 getTime()) && ((cmd_list[mCommands].getTime() > 0) ||
180 ((cmd_list[mCommands].getTime() == 0) && (cmd_list[mCommands].
181 getType() != MemCommand::PRE)))) {
182 full_cmd_list[i] = cmd_list[mCommands];
183 mCommands++;
184 } else if ((cached_cmd[mCached].getTime() > 0) && (cmd_list[mCommands].
185 getTime() >= cached_cmd[mCached].getTime())) {
186 full_cmd_list[i] = cached_cmd[mCached];
187 mCached++;
188 } else if (cached_cmd[mCached].getTime() == 0) {
189 if ((cmd_list[mCommands].getTime() > 0) || ((cmd_list[mCommands].
190 getTime() == 0) && (cmd_list[mCommands].
191 getType() != MemCommand::PRE))) {
192 full_cmd_list[i] = cmd_list[mCommands];
193 mCommands++;
194 }
195 } else if (cmd_list[mCommands].getTime() == 0) {
196 full_cmd_list[i] = cached_cmd[mCached];
197 mCached++;
198 }
199 }
200 } else {
201 if ((cmd_list[mCommands].getTime() > 1) && (init == 0)) {
202 full_cmd_list[i].setType(MemCommand::PREA);
203 init = 1;
204 pop = 1;
205 } else {
206 init = 1;
207 if ((cmd_list[mCommands].getTime() > 0) || ((cmd_list.
208 at(mCommands).getTime() == 0) && (cmd_list[mCommands].
209 getType() != MemCommand::PRE))) {
210 full_cmd_list[i] = cmd_list[mCommands];
211 mCommands++;
212 }
213 }
214 }
215 full_cmd_list.resize(full_cmd_list.size() + 1, MemCommand::PRE);
216 }
217
218 full_cmd_list.pop_back();
219 if (pop == 0) {
220 full_cmd_list.pop_back();
221 }
222 if (lastupdate) {
223 full_cmd_list.resize(full_cmd_list.size() + 1, MemCommand::NOP);
224 full_cmd_list[full_cmd_list.size() - 1].setTime(full_cmd_list
225 [full_cmd_list.size() - 2].getTime() + timeToCompletion(memSpec,
226 full_cmd_list[full_cmd_list.size() - 2].getType()) - 1);
227 }
228
229 evaluate(memSpec, full_cmd_list, nbrofBanks);
230 } // CommandAnalysis::analyse_commands
231
232 // To get the time of completion of the issued command
233 // Derived based on JEDEC specifications
234
235 int CommandAnalysis::timeToCompletion(const MemorySpecification&
236 memSpec, MemCommand::cmds type)
237 {
238 int offset = 0;
239 const MemTimingSpec& memTimingSpec = memSpec.memTimingSpec;
240 const MemArchitectureSpec& memArchSpec = memSpec.memArchSpec;
241
242 if (type == MemCommand::RD) {
243 offset = static_cast<int>(memTimingSpec.RL +
244 memTimingSpec.DQSCK + 1 + (memArchSpec.burstLength /
245 memArchSpec.dataRate));
246 } else if (type == MemCommand::WR) {
247 offset = static_cast<int>(memTimingSpec.WL +
248 (memArchSpec.burstLength / memArchSpec.dataRate) +
249 memTimingSpec.WR);
250 } else if (type == MemCommand::ACT) {
251 offset = static_cast<int>(memTimingSpec.RCD);
252 } else if ((type == MemCommand::PRE) || (type == MemCommand::PREA)) {
253 offset = static_cast<int>(memTimingSpec.RP);
254 }
255 return offset;
256 } // CommandAnalysis::timeToCompletion
257
258 // Used to analyse a given list of commands and identify command timings
259 // and memory state transitions
260 void CommandAnalysis::evaluate(const MemorySpecification& memSpec,
261 vector<MemCommand>& cmd_list, int nbrofBanks)
262 {
263 // for each command identify timestamp, type and bank
264 for (unsigned cmd_list_counter = 0; cmd_list_counter < cmd_list.size();
265 cmd_list_counter++) {
266 // For command type
267 int type = cmd_list[cmd_list_counter].getType();
268 // For command bank
269 int bank = cmd_list[cmd_list_counter].getBank();
270 // Command Issue timestamp in clock cycles (cc)
271 int64_t timestamp = cmd_list[cmd_list_counter].getTimeInt64();
272
273 if (type == MemCommand::ACT) {
274 // If command is ACT - update number of acts, bank state of the
275 // target bank, first and latest activation cycle and the memory
276 // state. Update the number of precharged/idle-precharged cycles.
277 numberofacts++;
278 if (bankstate[bank] == 1) {
279 printWarning("Bank is already active!", type, timestamp, bank);
280 }
281 bankstate[bank] = 1;
282 if (mem_state == 0) {
283 first_act_cycle = timestamp;
284 precycles += max(zero, timestamp - last_pre_cycle);
285 idle_pre_update(memSpec, timestamp, latest_pre_cycle);
286 }
287 latest_act_cycle = timestamp;
288 mem_state++;
289 } else if (type == MemCommand::RD) {
290 // If command is RD - update number of reads and read cycle. Check
291 // for active idle cycles (if any).
292 if (bankstate[bank] == 0) {
293 printWarning("Bank is not active!", type, timestamp, bank);
294 }
295 numberofreads++;
296 idle_act_update(memSpec, latest_read_cycle, latest_write_cycle,
297 latest_act_cycle, timestamp);
298 latest_read_cycle = timestamp;
299 } else if (type == MemCommand::WR) {
300 // If command is WR - update number of writes and write cycle. Check
301 // for active idle cycles (if any).
302 if (bankstate[bank] == 0) {
303 printWarning("Bank is not active!", type, timestamp, bank);
304 }
305 numberofwrites++;
306 idle_act_update(memSpec, latest_read_cycle, latest_write_cycle,
307 latest_act_cycle, timestamp);
308 latest_write_cycle = timestamp;
309 } else if (type == MemCommand::REF) {
310 // If command is REF - update number of refreshes, set bank state of
311 // all banks to ACT, set the last PRE cycles at RFC-RP cycles from
312 // timestamp, set the number of active cycles to RFC-RP and check
313 // for active and precharged cycles and idle active and idle
314 // precharged cycles before refresh. Change memory state to 0.
315 printWarningIfActive("One or more banks are active! REF requires all banks to be precharged.", type, timestamp, bank);
316 numberofrefs++;
317 idle_pre_update(memSpec, timestamp, latest_pre_cycle);
318 first_act_cycle = timestamp;
319 precycles += max(zero, timestamp - last_pre_cycle);
320 last_pre_cycle = timestamp + memSpec.memTimingSpec.RFC -
321 memSpec.memTimingSpec.RP;
322 latest_pre_cycle = last_pre_cycle;
323 actcycles += memSpec.memTimingSpec.RFC - memSpec.memTimingSpec.RP;
324 mem_state = 0;
325 for (int j = 0; j < nbrofBanks; j++) {
326 bankstate[j] = 0;
327 }
328 } else if (type == MemCommand::PRE) {
329 // If command is explicit PRE - update number of precharges, bank
330 // state of the target bank and last and latest precharge cycle.
331 // Calculate the number of active cycles if the memory was in the
332 // active state before, but there is a state transition to PRE now.
333 // If not, update the number of precharged cycles and idle cycles.
334 // Update memory state if needed.
335 if (bankstate[bank] == 1) {
336 numberofpres++;
337 }
338 bankstate[bank] = 0;
339
340 if (mem_state == 1) {
341 actcycles += max(zero, timestamp - first_act_cycle);
342 last_pre_cycle = timestamp;
343 idle_act_update(memSpec, latest_read_cycle, latest_write_cycle,
344 latest_act_cycle, timestamp);
345 } else if (mem_state == 0) {
346 precycles += max(zero, timestamp - last_pre_cycle);
347 idle_pre_update(memSpec, timestamp, latest_pre_cycle);
348 last_pre_cycle = timestamp;
349 }
350 latest_pre_cycle = timestamp;
351 if (mem_state > 0) {
352 mem_state--;
353 } else {
354 mem_state = 0;
355 }
356 } else if (type == MemCommand::PREA) {
357 // If command is explicit PREA (precharge all banks) - update
358 // number of precharges by the number of banks, update the bank
359 // state of all banks to PRE and set the precharge cycle.
360 // Calculate the number of active cycles if the memory was in the
361 // active state before, but there is a state transition to PRE now.
362 // If not, update the number of precharged cycles and idle cycles.
363 if (timestamp == 0) {
364 numberofpres += 0;
365 } else {
366 numberofpres += mem_state;
367 }
368
369 if (mem_state > 0) {
370 actcycles += max(zero, timestamp - first_act_cycle);
371 idle_act_update(memSpec, latest_read_cycle, latest_write_cycle,
372 latest_act_cycle, timestamp);
373 } else if (mem_state == 0) {
374 precycles += max(zero, timestamp - last_pre_cycle);
375 idle_pre_update(memSpec, timestamp, latest_pre_cycle);
376 }
377
378 latest_pre_cycle = timestamp;
379 last_pre_cycle = timestamp;
380
381 mem_state = 0;
382
383 for (int j = 0; j < nbrofBanks; j++) {
384 bankstate[j] = 0;
385 }
386 } else if (type == MemCommand::PDN_F_ACT) {
387 // If command is fast-exit active power-down - update number of
388 // power-downs, set the power-down cycle and the memory mode to
389 // fast-exit active power-down. Save states of all the banks from
390 // the cycle before entering active power-down, to be returned to
391 // after powering-up. Update active and active idle cycles.
392 printWarningIfNotActive("All banks are precharged! Incorrect use of Active Power-Down.", type, timestamp, bank);
393 f_act_pdns++;
394 for (int j = 0; j < nbrofBanks; j++) {
395 last_states[j] = bankstate[j];
396 }
397 pdn_cycle = timestamp;
398 actcycles += max(zero, timestamp - first_act_cycle);
399 idle_act_update(memSpec, latest_read_cycle, latest_write_cycle,
400 latest_act_cycle, timestamp);
401 mem_state = CommandAnalysis::MS_PDN_F_ACT;
402 } else if (type == MemCommand::PDN_S_ACT) {
403 // If command is slow-exit active power-down - update number of
404 // power-downs, set the power-down cycle and the memory mode to
405 // slow-exit active power-down. Save states of all the banks from
406 // the cycle before entering active power-down, to be returned to
407 // after powering-up. Update active and active idle cycles.
408 printWarningIfNotActive("All banks are precharged! Incorrect use of Active Power-Down.", type, timestamp, bank);
409 s_act_pdns++;
410 for (int j = 0; j < nbrofBanks; j++) {
411 last_states[j] = bankstate[j];
412 }
413 pdn_cycle = timestamp;
414 actcycles += max(zero, timestamp - first_act_cycle);
415 idle_act_update(memSpec, latest_read_cycle, latest_write_cycle,
416 latest_act_cycle, timestamp);
417 mem_state = CommandAnalysis::MS_PDN_S_ACT;
418 } else if (type == MemCommand::PDN_F_PRE) {
419 // If command is fast-exit precharged power-down - update number of
420 // power-downs, set the power-down cycle and the memory mode to
421 // fast-exit precahrged power-down. Update precharged and precharged
422 // idle cycles.
423 printWarningIfActive("One or more banks are active! Incorrect use of Precharged Power-Down.", type, timestamp, bank);
424 f_pre_pdns++;
425 pdn_cycle = timestamp;
426 precycles += max(zero, timestamp - last_pre_cycle);
427 idle_pre_update(memSpec, timestamp, latest_pre_cycle);
428 mem_state = CommandAnalysis::MS_PDN_F_PRE;
429 } else if (type == MemCommand::PDN_S_PRE) {
430 // If command is slow-exit precharged power-down - update number of
431 // power-downs, set the power-down cycle and the memory mode to
432 // slow-exit precahrged power-down. Update precharged and precharged
433 // idle cycles.
434 printWarningIfActive("One or more banks are active! Incorrect use of Precharged Power-Down.", type, timestamp, bank);
435 s_pre_pdns++;
436 pdn_cycle = timestamp;
437 precycles += max(zero, timestamp - last_pre_cycle);
438 idle_pre_update(memSpec, timestamp, latest_pre_cycle);
439 mem_state = CommandAnalysis::MS_PDN_S_PRE;
440 } else if (type == MemCommand::PUP_ACT) {
441 // If command is power-up in the active mode - check the power-down
442 // exit-mode employed (fast or slow), update the number of power-down
443 // and power-up cycles and the latest and first act cycle. Also, reset
444 // all the individual bank states to the respective saved states
445 // before entering power-down.
446 if (mem_state == CommandAnalysis::MS_PDN_F_ACT) {
447 f_act_pdcycles += max(zero, timestamp - pdn_cycle);
448 pup_act_cycles += memSpec.memTimingSpec.XP;
449 latest_act_cycle = max(timestamp, timestamp +
450 memSpec.memTimingSpec.XP - memSpec.memTimingSpec.RCD);
451 } else if (mem_state == CommandAnalysis::MS_PDN_S_ACT) {
452 s_act_pdcycles += max(zero, timestamp - pdn_cycle);
453 if (memSpec.memArchSpec.dll == false) {
454 pup_act_cycles += memSpec.memTimingSpec.XP;
455 latest_act_cycle = max(timestamp, timestamp +
456 memSpec.memTimingSpec.XP - memSpec.memTimingSpec.RCD);
457 } else {
458 pup_act_cycles += memSpec.memTimingSpec.XPDLL -
459 memSpec.memTimingSpec.RCD;
460 latest_act_cycle = max(timestamp, timestamp +
461 memSpec.memTimingSpec.XPDLL -
462 (2 * memSpec.memTimingSpec.RCD));
463 }
464 } else if ((mem_state != CommandAnalysis::MS_PDN_S_ACT) || (mem_state !=
465 CommandAnalysis::MS_PDN_F_ACT)) {
466 cerr << "Incorrect use of Active Power-Up!" << endl;
467 }
468 mem_state = 0;
469 for (int j = 0; j < nbrofBanks; j++) {
470 bankstate[j] = last_states[j];
471 mem_state += last_states[j];
472 }
473 first_act_cycle = timestamp;
474 } else if (type == MemCommand::PUP_PRE) {
475 // If command is power-up in the precharged mode - check the power-down
476 // exit-mode employed (fast or slow), update the number of power-down
477 // and power-up cycles and the latest and last pre cycle.
478 if (mem_state == CommandAnalysis::MS_PDN_F_PRE) {
479 f_pre_pdcycles += max(zero, timestamp - pdn_cycle);
480 pup_pre_cycles += memSpec.memTimingSpec.XP;
481 latest_pre_cycle = max(timestamp, timestamp +
482 memSpec.memTimingSpec.XP - memSpec.memTimingSpec.RP);
483 } else if (mem_state == CommandAnalysis::MS_PDN_S_PRE) {
484 s_pre_pdcycles += max(zero, timestamp - pdn_cycle);
485 if (memSpec.memArchSpec.dll == false) {
486 pup_pre_cycles += memSpec.memTimingSpec.XP;
487 latest_pre_cycle = max(timestamp, timestamp +
488 memSpec.memTimingSpec.XP - memSpec.memTimingSpec.RP);
489 } else {
490 pup_pre_cycles += memSpec.memTimingSpec.XPDLL -
491 memSpec.memTimingSpec.RCD;
492 latest_pre_cycle = max(timestamp, timestamp +
493 memSpec.memTimingSpec.XPDLL - memSpec.memTimingSpec.RCD -
494 memSpec.memTimingSpec.RP);
495 }
496 } else if ((mem_state != CommandAnalysis::MS_PDN_S_PRE) || (mem_state !=
497 CommandAnalysis::MS_PDN_F_PRE)) {
498 cerr << "Incorrect use of Precharged Power-Up!" << endl;
499 }
500 mem_state = 0;
501 last_pre_cycle = timestamp;
502 } else if (type == MemCommand::SREN) {
503 // If command is self-refresh - update number of self-refreshes,
504 // set memory state to SREF, update precharge and idle precharge
505 // cycles and set the self-refresh cycle.
506 printWarningIfActive("One or more banks are active! SREF requires all banks to be precharged.", type, timestamp, bank);
507 numberofsrefs++;
508 sref_cycle = timestamp;
509 precycles += max(zero, timestamp - last_pre_cycle);
510 idle_pre_update(memSpec, timestamp, latest_pre_cycle);
511 mem_state = CommandAnalysis::MS_SREF;
512 } else if (type == MemCommand::SREX) {
513 // If command is self-refresh exit - update the number of self-refresh
514 // clock cycles, number of active and precharged auto-refresh clock
515 // cycles during self-refresh and self-refresh exit based on the number
516 // of cycles in the self-refresh mode and auto-refresh duration (RFC).
517 // Set the last and latest precharge cycle accordingly and set the
518 // memory state to 0.
519 if (mem_state != CommandAnalysis::MS_SREF) {
520 cerr << "Incorrect use of Self-Refresh Power-Up!" << endl;
521 }
522 if (max(zero, timestamp - sref_cycle) >= memSpec.memTimingSpec.RFC) {
523 sref_cycles += max(zero, timestamp - sref_cycle
524 - memSpec.memTimingSpec.RFC);
525 sref_ref_act_cycles += memSpec.memTimingSpec.RFC -
526 memSpec.memTimingSpec.RP;
527 sref_ref_pre_cycles += memSpec.memTimingSpec.RP;
528 last_pre_cycle = timestamp;
529 if (memSpec.memArchSpec.dll == false) {
530 spup_cycles += memSpec.memTimingSpec.XS;
531 latest_pre_cycle = max(timestamp, timestamp +
532 memSpec.memTimingSpec.XS - memSpec.memTimingSpec.RP);
533 } else {
534 spup_cycles += memSpec.memTimingSpec.XSDLL -
535 memSpec.memTimingSpec.RCD;
536 latest_pre_cycle = max(timestamp, timestamp +
537 memSpec.memTimingSpec.XSDLL - memSpec.memTimingSpec.RCD
538 - memSpec.memTimingSpec.RP);
539 }
540 } else {
541 int64_t sref_diff = memSpec.memTimingSpec.RFC - memSpec.memTimingSpec.RP;
542 int64_t sref_pre = max(zero, timestamp - sref_cycle - sref_diff);
543 int64_t spup_pre = memSpec.memTimingSpec.RP - sref_pre;
544 int64_t sref_act = max(zero, timestamp - sref_cycle);
545 int64_t spup_act = memSpec.memTimingSpec.RFC - sref_act;
546
547 if (max(zero, timestamp - sref_cycle) >= sref_diff) {
548 sref_ref_act_cycles += sref_diff;
549 sref_ref_pre_cycles += sref_pre;
550 spup_ref_pre_cycles += spup_pre;
551 last_pre_cycle = timestamp + spup_pre;
552 if (memSpec.memArchSpec.dll == false) {
553 spup_cycles += memSpec.memTimingSpec.XS - spup_pre;
554 latest_pre_cycle = max(timestamp, timestamp +
555 memSpec.memTimingSpec.XS - spup_pre -
556 memSpec.memTimingSpec.RP);
557 } else {
558 spup_cycles += memSpec.memTimingSpec.XSDLL -
559 memSpec.memTimingSpec.RCD - spup_pre;
560 latest_pre_cycle = max(timestamp, timestamp +
561 memSpec.memTimingSpec.XSDLL - memSpec.memTimingSpec.RCD -
562 spup_pre - memSpec.memTimingSpec.RP);
563 }
564 } else {
565 sref_ref_act_cycles += sref_act;
566 spup_ref_act_cycles += spup_act;
567 spup_ref_pre_cycles += memSpec.memTimingSpec.RP;
568 last_pre_cycle = timestamp + spup_act + memSpec.memTimingSpec.RP;
569 if (memSpec.memArchSpec.dll == false) {
570 spup_cycles += memSpec.memTimingSpec.XS - spup_act -
571 memSpec.memTimingSpec.RP;
572 latest_pre_cycle = max(timestamp, timestamp +
573 memSpec.memTimingSpec.XS - spup_act -
574 (2 * memSpec.memTimingSpec.RP));
575 } else {
576 spup_cycles += memSpec.memTimingSpec.XSDLL -
577 memSpec.memTimingSpec.RCD - spup_act -
578 memSpec.memTimingSpec.RP;
579 latest_pre_cycle = max(timestamp, timestamp +
580 memSpec.memTimingSpec.XSDLL - memSpec.memTimingSpec.RCD -
581 spup_act - (2 * memSpec.memTimingSpec.RP));
582 }
583 }
584 }
585 mem_state = 0;
586 } else if ((type == MemCommand::END) || (type == MemCommand::NOP)) {
587 // May be optionally used at the end of memory trace for better accuracy
588 // Update all counters based on completion of operations.
589 if ((mem_state > 0) && (mem_state < 9)) {
590 actcycles += max(zero, timestamp - first_act_cycle);
591 idle_act_update(memSpec, latest_read_cycle, latest_write_cycle,
592 latest_act_cycle, timestamp);
593 } else if (mem_state == 0) {
594 precycles += max(zero, timestamp - last_pre_cycle);
595 idle_pre_update(memSpec, timestamp, latest_pre_cycle);
596 } else if (mem_state == CommandAnalysis::MS_PDN_F_ACT) {
597 f_act_pdcycles += max(zero, timestamp - pdn_cycle);
598 } else if (mem_state == CommandAnalysis::MS_PDN_S_ACT) {
599 s_act_pdcycles += max(zero, timestamp - pdn_cycle);
600 } else if (mem_state == CommandAnalysis::MS_PDN_F_PRE) {
601 f_pre_pdcycles += max(zero, timestamp - pdn_cycle);
602 } else if (mem_state == CommandAnalysis::MS_PDN_S_PRE) {
603 s_pre_pdcycles += max(zero, timestamp - pdn_cycle);
604 } else if (mem_state == CommandAnalysis::MS_SREF) {
605 sref_cycles += max(zero, timestamp - sref_cycle);
606 }
607 }
608 }
609 } // CommandAnalysis::evaluate
610
611 // To update idle period information whenever active cycles may be idle
612 void CommandAnalysis::idle_act_update(const MemorySpecification& memSpec,
613 int64_t latest_read_cycle, int64_t latest_write_cycle,
614 int64_t latest_act_cycle, int64_t timestamp)
615 {
616 if (latest_read_cycle >= 0) {
617 end_read_op = latest_read_cycle + timeToCompletion(memSpec,
618 MemCommand::RD) - 1;
619 }
620
621 if (latest_write_cycle >= 0) {
622 end_write_op = latest_write_cycle + timeToCompletion(memSpec,
623 MemCommand::WR) - 1;
624 }
625
626 if (latest_act_cycle >= 0) {
627 end_act_op = latest_act_cycle + timeToCompletion(memSpec,
628 MemCommand::ACT) - 1;
629 }
630
631 idlecycles_act += max(zero, timestamp - max(max(end_read_op, end_write_op),
632 end_act_op));
633 } // CommandAnalysis::idle_act_update
634
635 // To update idle period information whenever precharged cycles may be idle
636 void CommandAnalysis::idle_pre_update(const MemorySpecification& memSpec,
637 int64_t timestamp, int64_t latest_pre_cycle)
638 {
639 if (latest_pre_cycle > 0) {
640 idlecycles_pre += max(zero, timestamp - latest_pre_cycle -
641 memSpec.memTimingSpec.RP);
642 } else if (latest_pre_cycle == 0) {
643 idlecycles_pre += max(zero, timestamp - latest_pre_cycle);
644 }
645 }
646
647 void CommandAnalysis::printWarningIfActive(const string& warning, int type, int64_t timestamp, int bank)
648 {
649 if (mem_state != 0) {
650 printWarning(warning, type, timestamp, bank);
651 }
652 }
653
654 void CommandAnalysis::printWarningIfNotActive(const string& warning, int type, int64_t timestamp, int bank)
655 {
656 if (mem_state == 0) {
657 printWarning(warning, type, timestamp, bank);
658 }
659 }
660
661 void CommandAnalysis::printWarning(const string& warning, int type, int64_t timestamp, int bank)
662 {
663 cerr << "WARNING: " << warning << endl;
664 cerr << "Command: " << type << ", Timestamp: " << timestamp <<
665 ", Bank: " << bank << endl;
666 }