110428Sandreas.hansson@arm.com/*
210428Sandreas.hansson@arm.com * Copyright (c) 2012-2014, TU Delft
310428Sandreas.hansson@arm.com * Copyright (c) 2012-2014, TU Eindhoven
410428Sandreas.hansson@arm.com * Copyright (c) 2012-2014, TU Kaiserslautern
510428Sandreas.hansson@arm.com * All rights reserved.
610428Sandreas.hansson@arm.com *
710428Sandreas.hansson@arm.com * Redistribution and use in source and binary forms, with or without
810428Sandreas.hansson@arm.com * modification, are permitted provided that the following conditions are
910428Sandreas.hansson@arm.com * met:
1010428Sandreas.hansson@arm.com *
1110428Sandreas.hansson@arm.com * 1. Redistributions of source code must retain the above copyright
1210428Sandreas.hansson@arm.com * notice, this list of conditions and the following disclaimer.
1310428Sandreas.hansson@arm.com *
1410428Sandreas.hansson@arm.com * 2. Redistributions in binary form must reproduce the above copyright
1510428Sandreas.hansson@arm.com * notice, this list of conditions and the following disclaimer in the
1610428Sandreas.hansson@arm.com * documentation and/or other materials provided with the distribution.
1710428Sandreas.hansson@arm.com *
1810428Sandreas.hansson@arm.com * 3. Neither the name of the copyright holder nor the names of its
1910428Sandreas.hansson@arm.com * contributors may be used to endorse or promote products derived from
2010428Sandreas.hansson@arm.com * this software without specific prior written permission.
2110428Sandreas.hansson@arm.com *
2210428Sandreas.hansson@arm.com * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS
2310428Sandreas.hansson@arm.com * IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
2410428Sandreas.hansson@arm.com * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
2510428Sandreas.hansson@arm.com * PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
2610428Sandreas.hansson@arm.com * HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
2710428Sandreas.hansson@arm.com * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
2810428Sandreas.hansson@arm.com * TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
2910428Sandreas.hansson@arm.com * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
3010428Sandreas.hansson@arm.com * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
3110428Sandreas.hansson@arm.com * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
3210428Sandreas.hansson@arm.com * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
3310428Sandreas.hansson@arm.com *
3412266Sradhika.jagtap@arm.com * Authors: Karthik Chandrasekar,
3512266Sradhika.jagtap@arm.com *          Matthias Jung,
3612266Sradhika.jagtap@arm.com *          Omar Naji,
3712266Sradhika.jagtap@arm.com *          Sven Goossens,
3812266Sradhika.jagtap@arm.com *          Éder F. Zulian
3912266Sradhika.jagtap@arm.com *          Subash Kannoth
4012266Sradhika.jagtap@arm.com *          Felipe S. Prado
4110428Sandreas.hansson@arm.com *
4210428Sandreas.hansson@arm.com */
4310428Sandreas.hansson@arm.com
4410428Sandreas.hansson@arm.com#include <fstream>
4510428Sandreas.hansson@arm.com#include <algorithm>
4610428Sandreas.hansson@arm.com#include <sstream>
4710428Sandreas.hansson@arm.com
4810428Sandreas.hansson@arm.com#include "CommandAnalysis.h"
4910428Sandreas.hansson@arm.com#include "CmdScheduler.h"
5010428Sandreas.hansson@arm.com
5110428Sandreas.hansson@arm.comusing namespace Data;
5210428Sandreas.hansson@arm.comusing namespace std;
5310428Sandreas.hansson@arm.com
5411555Sjungma@eit.uni-kl.debool commandSorter(const MemCommand& i, const MemCommand& j)
5510428Sandreas.hansson@arm.com{
5611555Sjungma@eit.uni-kl.de  if (i.getTimeInt64() == j.getTimeInt64()) {
5711555Sjungma@eit.uni-kl.de    return i.getType() == MemCommand::PRE && j.getType() != MemCommand::PRE;
5811555Sjungma@eit.uni-kl.de  } else {
5911555Sjungma@eit.uni-kl.de    return i.getTimeInt64() < j.getTimeInt64();
6011555Sjungma@eit.uni-kl.de  }
6110428Sandreas.hansson@arm.com}
6210428Sandreas.hansson@arm.com
6312266Sradhika.jagtap@arm.comCommandAnalysis::CommandAnalysis(const Data::MemorySpecification& memSpec) :
6412266Sradhika.jagtap@arm.com  memSpec(memSpec)
6512266Sradhika.jagtap@arm.com
6610428Sandreas.hansson@arm.com{
6712266Sradhika.jagtap@arm.com  auto &nBanks = memSpec.memArchSpec.nbrOfBanks;
6810428Sandreas.hansson@arm.com  // Initializing all counters and variables
6912266Sradhika.jagtap@arm.com  numberofactsBanks.assign(static_cast<size_t>(nBanks), 0);
7012266Sradhika.jagtap@arm.com  numberofpresBanks.assign(static_cast<size_t>(nBanks), 0);
7112266Sradhika.jagtap@arm.com  numberofreadsBanks.assign(static_cast<size_t>(nBanks), 0);
7212266Sradhika.jagtap@arm.com  numberofwritesBanks.assign(static_cast<size_t>(nBanks), 0);
7312266Sradhika.jagtap@arm.com  actcyclesBanks.assign(static_cast<size_t>(nBanks), 0);
7412266Sradhika.jagtap@arm.com  numberofrefbBanks.assign(static_cast<size_t>(nBanks), 0);
7512266Sradhika.jagtap@arm.com
7612266Sradhika.jagtap@arm.com  first_act_cycle_banks.resize(static_cast<size_t>(nBanks), 0);
7712266Sradhika.jagtap@arm.com
7811555Sjungma@eit.uni-kl.de  clearStats(0);
7911555Sjungma@eit.uni-kl.de  zero = 0;
8011555Sjungma@eit.uni-kl.de
8112266Sradhika.jagtap@arm.com  bank_state.resize(static_cast<size_t>(nBanks), BANK_PRECHARGED);
8212266Sradhika.jagtap@arm.com  last_bank_state.resize(static_cast<size_t>(nBanks), BANK_PRECHARGED);
8312266Sradhika.jagtap@arm.com  mem_state  = MS_NOT_IN_PD;
8411555Sjungma@eit.uni-kl.de
8511555Sjungma@eit.uni-kl.de  cmd_list.clear();
8611555Sjungma@eit.uni-kl.de  cached_cmd.clear();
8712266Sradhika.jagtap@arm.com  activation_cycle.resize(static_cast<size_t>(nBanks), 0);
8812266Sradhika.jagtap@arm.com  num_banks = nBanks;
8911555Sjungma@eit.uni-kl.de}
9011555Sjungma@eit.uni-kl.de
9111555Sjungma@eit.uni-kl.de// function to clear counters
9211555Sjungma@eit.uni-kl.devoid CommandAnalysis::clearStats(const int64_t timestamp)
9311555Sjungma@eit.uni-kl.de{
9412266Sradhika.jagtap@arm.com  std::fill(numberofactsBanks.begin(), numberofactsBanks.end(), 0);
9512266Sradhika.jagtap@arm.com  std::fill(numberofpresBanks.begin(), numberofpresBanks.end(), 0);
9612266Sradhika.jagtap@arm.com  std::fill(numberofreadsBanks.begin(), numberofreadsBanks.end(), 0);
9712266Sradhika.jagtap@arm.com  std::fill(numberofwritesBanks.begin(), numberofwritesBanks.end(), 0);
9812266Sradhika.jagtap@arm.com  std::fill(actcyclesBanks.begin(), actcyclesBanks.end(), 0);
9910428Sandreas.hansson@arm.com
10010428Sandreas.hansson@arm.com  numberofrefs        = 0;
10110428Sandreas.hansson@arm.com  f_act_pdns          = 0;
10210428Sandreas.hansson@arm.com  s_act_pdns          = 0;
10310428Sandreas.hansson@arm.com  f_pre_pdns          = 0;
10410428Sandreas.hansson@arm.com  s_pre_pdns          = 0;
10510428Sandreas.hansson@arm.com  numberofsrefs       = 0;
10610428Sandreas.hansson@arm.com
10710428Sandreas.hansson@arm.com  actcycles           = 0;
10810428Sandreas.hansson@arm.com  precycles           = 0;
10910428Sandreas.hansson@arm.com  f_act_pdcycles      = 0;
11010428Sandreas.hansson@arm.com  s_act_pdcycles      = 0;
11110428Sandreas.hansson@arm.com  f_pre_pdcycles      = 0;
11210428Sandreas.hansson@arm.com  s_pre_pdcycles      = 0;
11310428Sandreas.hansson@arm.com  pup_act_cycles      = 0;
11410428Sandreas.hansson@arm.com  pup_pre_cycles      = 0;
11510428Sandreas.hansson@arm.com  sref_cycles         = 0;
11610428Sandreas.hansson@arm.com  spup_cycles         = 0;
11710428Sandreas.hansson@arm.com  sref_ref_act_cycles = 0;
11810428Sandreas.hansson@arm.com  sref_ref_pre_cycles = 0;
11910428Sandreas.hansson@arm.com  spup_ref_act_cycles = 0;
12010428Sandreas.hansson@arm.com  spup_ref_pre_cycles = 0;
12110428Sandreas.hansson@arm.com  idlecycles_act      = 0;
12210428Sandreas.hansson@arm.com  idlecycles_pre      = 0;
12310428Sandreas.hansson@arm.com
12411555Sjungma@eit.uni-kl.de  // reset count references to timestamp so that they are moved
12511555Sjungma@eit.uni-kl.de  // to start of next stats generation
12612266Sradhika.jagtap@arm.com  std::fill(first_act_cycle_banks.begin(), first_act_cycle_banks.end(), timestamp);
12711555Sjungma@eit.uni-kl.de  first_act_cycle     = timestamp;
12812266Sradhika.jagtap@arm.com
12911555Sjungma@eit.uni-kl.de  pdn_cycle           = timestamp;
13012266Sradhika.jagtap@arm.com  sref_cycle_window   = timestamp;
13112266Sradhika.jagtap@arm.com
13211555Sjungma@eit.uni-kl.de  end_act_op          = timestamp;
13311555Sjungma@eit.uni-kl.de  end_read_op         = timestamp;
13411555Sjungma@eit.uni-kl.de  end_write_op        = timestamp;
13511555Sjungma@eit.uni-kl.de
13610428Sandreas.hansson@arm.com  latest_read_cycle   = -1;
13710428Sandreas.hansson@arm.com  latest_write_cycle  = -1;
13810428Sandreas.hansson@arm.com
13911555Sjungma@eit.uni-kl.de  if (timestamp == 0) {
14012266Sradhika.jagtap@arm.com    latest_pre_cycle = -1;
14112266Sradhika.jagtap@arm.com    latest_act_cycle = -1;
14212266Sradhika.jagtap@arm.com    sref_cycle = 0;
14312266Sradhika.jagtap@arm.com    last_pre_cycle = 0;
14412266Sradhika.jagtap@arm.com    sref_ref_act_cycles_window = 0;
14512266Sradhika.jagtap@arm.com    sref_ref_pre_cycles_window = 0;
14611555Sjungma@eit.uni-kl.de  } else {
14712266Sradhika.jagtap@arm.com    last_pre_cycle = max(timestamp,last_pre_cycle);
14812266Sradhika.jagtap@arm.com
14912266Sradhika.jagtap@arm.com    latest_pre_cycle = max(timestamp, latest_pre_cycle);
15012266Sradhika.jagtap@arm.com
15112266Sradhika.jagtap@arm.com    if (latest_act_cycle < timestamp)
15212266Sradhika.jagtap@arm.com        latest_act_cycle = -1;
15311555Sjungma@eit.uni-kl.de  }
15410428Sandreas.hansson@arm.com}
15510428Sandreas.hansson@arm.com
15610428Sandreas.hansson@arm.com// function to clear all arrays
15710428Sandreas.hansson@arm.comvoid CommandAnalysis::clear()
15810428Sandreas.hansson@arm.com{
15910428Sandreas.hansson@arm.com  cached_cmd.clear();
16010428Sandreas.hansson@arm.com  cmd_list.clear();
16112266Sradhika.jagtap@arm.com  last_bank_state.clear();
16212266Sradhika.jagtap@arm.com  bank_state.clear();
16310428Sandreas.hansson@arm.com}
16410428Sandreas.hansson@arm.com
16510428Sandreas.hansson@arm.com// Reads through the trace file, identifies the timestamp, command and bank
16610428Sandreas.hansson@arm.com// If the issued command includes an auto-precharge, adds an explicit
16710428Sandreas.hansson@arm.com// precharge to a cached command list and computes the precharge offset from the
16810428Sandreas.hansson@arm.com// issued command timestamp, when the auto-precharge would kick in
16910428Sandreas.hansson@arm.com
17012266Sradhika.jagtap@arm.comvoid CommandAnalysis::getCommands(std::vector<MemCommand>& list, bool lastupdate, int64_t timestamp)
17110428Sandreas.hansson@arm.com{
17212266Sradhika.jagtap@arm.com  if (!next_window_cmd_list.empty()) {
17312266Sradhika.jagtap@arm.com    list.insert(list.begin(), next_window_cmd_list.begin(), next_window_cmd_list.end());
17412266Sradhika.jagtap@arm.com    next_window_cmd_list.clear();
17512266Sradhika.jagtap@arm.com  }
17611555Sjungma@eit.uni-kl.de  for (size_t i = 0; i < list.size(); ++i) {
17711555Sjungma@eit.uni-kl.de    MemCommand& cmd = list[i];
17810428Sandreas.hansson@arm.com    MemCommand::cmds cmdType = cmd.getType();
17910428Sandreas.hansson@arm.com    if (cmdType == MemCommand::ACT) {
18010428Sandreas.hansson@arm.com      activation_cycle[cmd.getBank()] = cmd.getTimeInt64();
18110428Sandreas.hansson@arm.com    } else if (cmdType == MemCommand::RDA || cmdType == MemCommand::WRA) {
18210428Sandreas.hansson@arm.com      // Remove auto-precharge flag from command
18311555Sjungma@eit.uni-kl.de      cmd.setType(cmd.typeWithoutAutoPrechargeFlag());
18410428Sandreas.hansson@arm.com
18510428Sandreas.hansson@arm.com      // Add the auto precharge to the list of cached_cmds
18610428Sandreas.hansson@arm.com      int64_t preTime = max(cmd.getTimeInt64() + cmd.getPrechargeOffset(memSpec, cmdType),
18710428Sandreas.hansson@arm.com                           activation_cycle[cmd.getBank()] + memSpec.memTimingSpec.RAS);
18811555Sjungma@eit.uni-kl.de      list.push_back(MemCommand(MemCommand::PRE, cmd.getBank(), preTime));
18910428Sandreas.hansson@arm.com    }
19012266Sradhika.jagtap@arm.com
19112266Sradhika.jagtap@arm.com    if (!lastupdate && timestamp > 0) {
19212266Sradhika.jagtap@arm.com      if(cmd.getTimeInt64() > timestamp)
19312266Sradhika.jagtap@arm.com      {
19412266Sradhika.jagtap@arm.com          MemCommand nextWindowCmd = list[i];
19512266Sradhika.jagtap@arm.com          next_window_cmd_list.push_back(nextWindowCmd);
19612266Sradhika.jagtap@arm.com          list.erase(find(list.begin(), list.end(), cmd));
19712266Sradhika.jagtap@arm.com      }
19812266Sradhika.jagtap@arm.com    }
19910428Sandreas.hansson@arm.com  }
20011555Sjungma@eit.uni-kl.de  sort(list.begin(), list.end(), commandSorter);
20111555Sjungma@eit.uni-kl.de
20211555Sjungma@eit.uni-kl.de  if (lastupdate && list.empty() == false) {
20311555Sjungma@eit.uni-kl.de    // Add cycles at the end of the list
20412266Sradhika.jagtap@arm.com    int64_t t = timeToCompletion(list.back().getType()) + list.back().getTimeInt64() - 1;
20511555Sjungma@eit.uni-kl.de    list.push_back(MemCommand(MemCommand::NOP, 0, t));
20611555Sjungma@eit.uni-kl.de  }
20711555Sjungma@eit.uni-kl.de
20812266Sradhika.jagtap@arm.com  evaluateCommands(list);
20910428Sandreas.hansson@arm.com} // CommandAnalysis::getCommands
21010428Sandreas.hansson@arm.com
21110428Sandreas.hansson@arm.com
21210428Sandreas.hansson@arm.com// Used to analyse a given list of commands and identify command timings
21310428Sandreas.hansson@arm.com// and memory state transitions
21412266Sradhika.jagtap@arm.comvoid CommandAnalysis::evaluateCommands(vector<MemCommand>& cmd_list)
21510428Sandreas.hansson@arm.com{
21610428Sandreas.hansson@arm.com  // for each command identify timestamp, type and bank
21711555Sjungma@eit.uni-kl.de  for (auto cmd : cmd_list) {
21810428Sandreas.hansson@arm.com    // For command type
21911555Sjungma@eit.uni-kl.de    int type = cmd.getType();
22010428Sandreas.hansson@arm.com    // For command bank
22112266Sradhika.jagtap@arm.com    unsigned bank = cmd.getBank();
22210428Sandreas.hansson@arm.com    // Command Issue timestamp in clock cycles (cc)
22311555Sjungma@eit.uni-kl.de    int64_t timestamp = cmd.getTimeInt64();
22410428Sandreas.hansson@arm.com
22510428Sandreas.hansson@arm.com    if (type == MemCommand::ACT) {
22612266Sradhika.jagtap@arm.com      handleAct(bank, timestamp);
22710428Sandreas.hansson@arm.com    } else if (type == MemCommand::RD) {
22812266Sradhika.jagtap@arm.com      handleRd(bank, timestamp);
22910428Sandreas.hansson@arm.com    } else if (type == MemCommand::WR) {
23012266Sradhika.jagtap@arm.com      handleWr(bank, timestamp);
23110428Sandreas.hansson@arm.com    } else if (type == MemCommand::REF) {
23212266Sradhika.jagtap@arm.com      handleRef(bank, timestamp);
23312266Sradhika.jagtap@arm.com    } else if (type == MemCommand::REFB) {
23412266Sradhika.jagtap@arm.com      handleRefB(bank, timestamp);
23510428Sandreas.hansson@arm.com    } else if (type == MemCommand::PRE) {
23612266Sradhika.jagtap@arm.com      handlePre(bank, timestamp);
23710428Sandreas.hansson@arm.com    } else if (type == MemCommand::PREA) {
23812266Sradhika.jagtap@arm.com      handlePreA(bank, timestamp);
23910428Sandreas.hansson@arm.com    } else if (type == MemCommand::PDN_F_ACT) {
24012266Sradhika.jagtap@arm.com      handlePdnFAct(bank, timestamp);
24110428Sandreas.hansson@arm.com    } else if (type == MemCommand::PDN_S_ACT) {
24212266Sradhika.jagtap@arm.com      handlePdnSAct(bank, timestamp);
24310428Sandreas.hansson@arm.com    } else if (type == MemCommand::PDN_F_PRE) {
24412266Sradhika.jagtap@arm.com      handlePdnFPre(bank, timestamp);
24510428Sandreas.hansson@arm.com    } else if (type == MemCommand::PDN_S_PRE) {
24612266Sradhika.jagtap@arm.com      handlePdnSPre(bank, timestamp);
24710428Sandreas.hansson@arm.com    } else if (type == MemCommand::PUP_ACT) {
24812266Sradhika.jagtap@arm.com      handlePupAct(timestamp);
24910428Sandreas.hansson@arm.com    } else if (type == MemCommand::PUP_PRE) {
25012266Sradhika.jagtap@arm.com      handlePupPre(timestamp);
25110428Sandreas.hansson@arm.com    } else if (type == MemCommand::SREN) {
25212266Sradhika.jagtap@arm.com      handleSREn(bank, timestamp);
25310428Sandreas.hansson@arm.com    } else if (type == MemCommand::SREX) {
25412266Sradhika.jagtap@arm.com      handleSREx(bank, timestamp);
25511555Sjungma@eit.uni-kl.de    } else if (type == MemCommand::END || type == MemCommand::NOP) {
25612266Sradhika.jagtap@arm.com      handleNopEnd(timestamp);
25711555Sjungma@eit.uni-kl.de    } else {
25811555Sjungma@eit.uni-kl.de      printWarning("Unknown command given, exiting.", type, timestamp, bank);
25911555Sjungma@eit.uni-kl.de      exit(-1);
26010428Sandreas.hansson@arm.com    }
26110428Sandreas.hansson@arm.com  }
26212266Sradhika.jagtap@arm.com} // CommandAnalysis::evaluateCommands
26310428Sandreas.hansson@arm.com
26410428Sandreas.hansson@arm.com// To update idle period information whenever active cycles may be idle
26512266Sradhika.jagtap@arm.comvoid CommandAnalysis::idle_act_update(int64_t latest_read_cycle, int64_t latest_write_cycle,
26610428Sandreas.hansson@arm.com                                      int64_t latest_act_cycle, int64_t timestamp)
26710428Sandreas.hansson@arm.com{
26810428Sandreas.hansson@arm.com  if (latest_read_cycle >= 0) {
26912266Sradhika.jagtap@arm.com    end_read_op = latest_read_cycle + timeToCompletion(MemCommand::RD) - 1;
27010428Sandreas.hansson@arm.com  }
27110428Sandreas.hansson@arm.com
27210428Sandreas.hansson@arm.com  if (latest_write_cycle >= 0) {
27312266Sradhika.jagtap@arm.com    end_write_op = latest_write_cycle + timeToCompletion(MemCommand::WR) - 1;
27410428Sandreas.hansson@arm.com  }
27510428Sandreas.hansson@arm.com
27610428Sandreas.hansson@arm.com  if (latest_act_cycle >= 0) {
27712266Sradhika.jagtap@arm.com    end_act_op = latest_act_cycle + timeToCompletion(MemCommand::ACT) - 1;
27810428Sandreas.hansson@arm.com  }
27910428Sandreas.hansson@arm.com
28010428Sandreas.hansson@arm.com  idlecycles_act += max(zero, timestamp - max(max(end_read_op, end_write_op),
28110428Sandreas.hansson@arm.com                                              end_act_op));
28210428Sandreas.hansson@arm.com} // CommandAnalysis::idle_act_update
28310428Sandreas.hansson@arm.com
28410428Sandreas.hansson@arm.com// To update idle period information whenever precharged cycles may be idle
28512266Sradhika.jagtap@arm.comvoid CommandAnalysis::idle_pre_update(int64_t timestamp, int64_t latest_pre_cycle)
28610428Sandreas.hansson@arm.com{
28710428Sandreas.hansson@arm.com  if (latest_pre_cycle > 0) {
28810428Sandreas.hansson@arm.com    idlecycles_pre += max(zero, timestamp - latest_pre_cycle -
28910428Sandreas.hansson@arm.com                          memSpec.memTimingSpec.RP);
29010428Sandreas.hansson@arm.com  } else if (latest_pre_cycle == 0) {
29110428Sandreas.hansson@arm.com    idlecycles_pre += max(zero, timestamp - latest_pre_cycle);
29210428Sandreas.hansson@arm.com  }
29310428Sandreas.hansson@arm.com}
29410428Sandreas.hansson@arm.com
295