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 *
3411555Sjungma@eit.uni-kl.de * Authors: Karthik Chandrasekar, Yonghui Li, Sven Goossens
3510428Sandreas.hansson@arm.com *
3610428Sandreas.hansson@arm.com */
3710428Sandreas.hansson@arm.com#include "CmdScheduler.h"
3810428Sandreas.hansson@arm.com
3910428Sandreas.hansson@arm.com#include <cassert>
4010428Sandreas.hansson@arm.com#include <cmath>  // For log2
4110428Sandreas.hansson@arm.com
4210428Sandreas.hansson@arm.com#include <algorithm>  // For max
4310428Sandreas.hansson@arm.com
4410428Sandreas.hansson@arm.com
4511555Sjungma@eit.uni-kl.de#define MILLION 1000000
4611555Sjungma@eit.uni-kl.de
4711555Sjungma@eit.uni-kl.de
4810428Sandreas.hansson@arm.comusing namespace std;
4910428Sandreas.hansson@arm.comusing namespace Data;
5010428Sandreas.hansson@arm.com
5110428Sandreas.hansson@arm.com// Read the traces and get the transaction. Each transaction is executed by
5210428Sandreas.hansson@arm.com// scheduling a number of commands to the memory. Hence, the transactions are
5310428Sandreas.hansson@arm.com// translated into a sequence of commands which will be used for power analysis.
5411555Sjungma@eit.uni-kl.devoid cmdScheduler::transTranslation(const MemorySpecification& memSpec,
5510428Sandreas.hansson@arm.com                                    ifstream& trans_trace, int grouping, int interleaving, int burst, int powerdown)
5610428Sandreas.hansson@arm.com{
5710428Sandreas.hansson@arm.com  commands.open("commands.trace", ifstream::out);
5811555Sjungma@eit.uni-kl.de  const MemArchitectureSpec& memArchSpec = memSpec.memArchSpec;
5910428Sandreas.hansson@arm.com  nBanks          = memArchSpec.nbrOfBanks;
6010428Sandreas.hansson@arm.com  nColumns        = memArchSpec.nbrOfColumns;
6110428Sandreas.hansson@arm.com  burstLength     = memArchSpec.burstLength;
6210428Sandreas.hansson@arm.com  nbrOfBankGroups = memArchSpec.nbrOfBankGroups;
6310428Sandreas.hansson@arm.com
6410428Sandreas.hansson@arm.com  BGI             = grouping;
6510428Sandreas.hansson@arm.com  BI = interleaving;
6610428Sandreas.hansson@arm.com  BC = burst;
6710428Sandreas.hansson@arm.com  power_down      = powerdown;
6810428Sandreas.hansson@arm.com
6910428Sandreas.hansson@arm.com  schedulingInitialization(memSpec);
7010428Sandreas.hansson@arm.com  getTrans(trans_trace, memSpec);
7110428Sandreas.hansson@arm.com
7210428Sandreas.hansson@arm.com  trans_trace.close();
7310428Sandreas.hansson@arm.com  commands.close();
7410428Sandreas.hansson@arm.com  ACT.erase(ACT.begin(), ACT.end());
7510428Sandreas.hansson@arm.com  PRE.erase(PRE.begin(), PRE.end());
7610428Sandreas.hansson@arm.com  RDWR.erase(RDWR.begin(), RDWR.end());
7710428Sandreas.hansson@arm.com  cmdScheduling.erase(cmdScheduling.begin(), cmdScheduling.end());
7810428Sandreas.hansson@arm.com  cmdList.erase(cmdList.begin(), cmdList.end());
7910428Sandreas.hansson@arm.com  transTrace.erase(transTrace.begin(), transTrace.end());
8010428Sandreas.hansson@arm.com} // cmdScheduler::transTranslation
8110428Sandreas.hansson@arm.com
8210428Sandreas.hansson@arm.com// initialize the variables and vectors for starting command scheduling.
8311555Sjungma@eit.uni-kl.devoid cmdScheduler::schedulingInitialization(const MemorySpecification& memSpec)
8410428Sandreas.hansson@arm.com{
8511555Sjungma@eit.uni-kl.de  const MemTimingSpec& memTimingSpec = memSpec.memTimingSpec;
8610428Sandreas.hansson@arm.com
8711555Sjungma@eit.uni-kl.de  const size_t numBanks = static_cast<size_t>(memSpec.memArchSpec.nbrOfBanks);
8811555Sjungma@eit.uni-kl.de  ACT.resize(2 * numBanks);
8911555Sjungma@eit.uni-kl.de  RDWR.resize(2 * numBanks);
9011555Sjungma@eit.uni-kl.de  PRE.resize(numBanks);
9110428Sandreas.hansson@arm.com  bankaccess = memSpec.memArchSpec.nbrOfBanks;
9210428Sandreas.hansson@arm.com  if (!ACT.empty()) {
9310428Sandreas.hansson@arm.com    ACT.erase(ACT.begin(), ACT.end());
9410428Sandreas.hansson@arm.com  }
9510428Sandreas.hansson@arm.com  if (!PRE.empty()) {
9610428Sandreas.hansson@arm.com    PRE.erase(PRE.begin(), PRE.end());
9710428Sandreas.hansson@arm.com  }
9810428Sandreas.hansson@arm.com  if (!RDWR.empty()) {
9910428Sandreas.hansson@arm.com    RDWR.erase(RDWR.begin(), RDWR.end());
10010428Sandreas.hansson@arm.com  }
10110428Sandreas.hansson@arm.com
10210428Sandreas.hansson@arm.com  ///////////////initialization//////////////
10311555Sjungma@eit.uni-kl.de  for (int64_t i = 0; i < memSpec.memArchSpec.nbrOfBanks; i++) {
10410428Sandreas.hansson@arm.com    cmd.Type = PRECHARGE;
10511555Sjungma@eit.uni-kl.de    cmd.bank = static_cast<unsigned>(i);
10610428Sandreas.hansson@arm.com    cmd.name = "PRE";
10711555Sjungma@eit.uni-kl.de    if (memSpec.id == "WIDEIO_SDR") {
10811555Sjungma@eit.uni-kl.de      cmd.time = 1 - memSpec.memTimingSpec.TAW;
10911555Sjungma@eit.uni-kl.de    } else {
11011555Sjungma@eit.uni-kl.de      cmd.time = 1 - memSpec.memTimingSpec.FAW;
11111555Sjungma@eit.uni-kl.de    }
11210428Sandreas.hansson@arm.com
11310428Sandreas.hansson@arm.com    PRE.push_back(cmd);
11410428Sandreas.hansson@arm.com
11510428Sandreas.hansson@arm.com    cmd.Type = ACTIVATE;
11610428Sandreas.hansson@arm.com    cmd.name = "ACT";
11710428Sandreas.hansson@arm.com    ACT.push_back(cmd);
11810428Sandreas.hansson@arm.com
11910428Sandreas.hansson@arm.com    cmd.Type = WRITE;
12010428Sandreas.hansson@arm.com    cmd.name = "WRITE";
12110428Sandreas.hansson@arm.com    cmd.time = -1;
12211555Sjungma@eit.uni-kl.de    RDWR[static_cast<size_t>(i)].push_back(cmd);
12310428Sandreas.hansson@arm.com  }
12410428Sandreas.hansson@arm.com  tREF             = memTimingSpec.REFI;
12510428Sandreas.hansson@arm.com  transFinish.time = 0;
12610428Sandreas.hansson@arm.com  transFinish.bank = 0;
12710428Sandreas.hansson@arm.com
12810428Sandreas.hansson@arm.com  PreRDWR.bank     = -1;
12910428Sandreas.hansson@arm.com  PreRDWR.Type     = READ;
13010428Sandreas.hansson@arm.com  PreRDWR.name     = "RD";
13110428Sandreas.hansson@arm.com  PreRDWR.time     = -1;
13210428Sandreas.hansson@arm.com  startTime        = 0;
13310428Sandreas.hansson@arm.com} // cmdScheduler::schedulingInitialization
13410428Sandreas.hansson@arm.com
13510428Sandreas.hansson@arm.com// transactions are generated according to the information read from the traces.
13610428Sandreas.hansson@arm.com// Then the command scheduling function is triggered to generate commands and
13710428Sandreas.hansson@arm.com// schedule them to the memory according to the timing constraints.
13811555Sjungma@eit.uni-kl.devoid cmdScheduler::getTrans(std::ifstream& trans_trace, const MemorySpecification& memSpec)
13910428Sandreas.hansson@arm.com{
14010428Sandreas.hansson@arm.com  std::string line;
14110428Sandreas.hansson@arm.com
14210428Sandreas.hansson@arm.com  transTime = 0;
14311555Sjungma@eit.uni-kl.de  uint64_t newtranstime;
14411555Sjungma@eit.uni-kl.de  uint64_t transAddr;
14511555Sjungma@eit.uni-kl.de  int64_t transType = 1;
14610428Sandreas.hansson@arm.com  trans    TransItem;
14710428Sandreas.hansson@arm.com
14810428Sandreas.hansson@arm.com  if (!transTrace.empty()) {
14910428Sandreas.hansson@arm.com    transTrace.erase(transTrace.begin(), transTrace.end());
15010428Sandreas.hansson@arm.com  }
15110428Sandreas.hansson@arm.com
15210428Sandreas.hansson@arm.com  while (getline(trans_trace, line)) {
15310428Sandreas.hansson@arm.com    istringstream linestream(line);
15410428Sandreas.hansson@arm.com    string item;
15511555Sjungma@eit.uni-kl.de    uint64_t itemnum = 0;
15610428Sandreas.hansson@arm.com    while (getline(linestream, item, ',')) {
15710428Sandreas.hansson@arm.com      if (itemnum == 0) {
15810428Sandreas.hansson@arm.com        stringstream timestamp(item);
15910428Sandreas.hansson@arm.com        timestamp >> newtranstime;
16011555Sjungma@eit.uni-kl.de        transTime = transTime + static_cast<int64_t>(newtranstime);
16110428Sandreas.hansson@arm.com      } else if (itemnum == 1) {
16210428Sandreas.hansson@arm.com        if (item  == "write" || item == "WRITE") {
16310428Sandreas.hansson@arm.com          transType = WRITE;
16410428Sandreas.hansson@arm.com        } else   {
16510428Sandreas.hansson@arm.com          transType = READ;
16610428Sandreas.hansson@arm.com        }
16710428Sandreas.hansson@arm.com      } else if (itemnum == 2) {
16810428Sandreas.hansson@arm.com        stringstream timestamp(item);
16910428Sandreas.hansson@arm.com        timestamp >> std::hex >> transAddr;
17010428Sandreas.hansson@arm.com      }
17110428Sandreas.hansson@arm.com      itemnum++;
17210428Sandreas.hansson@arm.com    }
17310428Sandreas.hansson@arm.com    // generate a transaction
17410428Sandreas.hansson@arm.com    TransItem.timeStamp      = transTime;
17510428Sandreas.hansson@arm.com    TransItem.logicalAddress = transAddr;
17610428Sandreas.hansson@arm.com    TransItem.type           = transType;
17710428Sandreas.hansson@arm.com
17810428Sandreas.hansson@arm.com    transTrace.push_back(TransItem);
17910428Sandreas.hansson@arm.com
18010428Sandreas.hansson@arm.com    if (transTrace.size() == MILLION) {
18110428Sandreas.hansson@arm.com      // The scheduling is implemented for every MILLION transactions.
18210428Sandreas.hansson@arm.com      // It is used to reduce the used memory during the running of this tool.
18310428Sandreas.hansson@arm.com      analyticalScheduling(memSpec);
18410428Sandreas.hansson@arm.com      transTrace.erase(transTrace.begin(), transTrace.end());
18510428Sandreas.hansson@arm.com    }
18610428Sandreas.hansson@arm.com  }
18710428Sandreas.hansson@arm.com
18810428Sandreas.hansson@arm.com  if ((transTrace.size() < MILLION) && (!transTrace.empty())) {
18910428Sandreas.hansson@arm.com    analyticalScheduling(memSpec);
19010428Sandreas.hansson@arm.com    transTrace.erase(transTrace.begin(), transTrace.end());
19110428Sandreas.hansson@arm.com  }
19210428Sandreas.hansson@arm.com} // cmdScheduler::getTrans
19310428Sandreas.hansson@arm.com
19410428Sandreas.hansson@arm.com// Transactions are executed individually and the command scheduling is
19510428Sandreas.hansson@arm.com// independent between transactions. The commands for a new transaction cannot
19610428Sandreas.hansson@arm.com// be scheduled until all the commands for the current one are scheduled.
19710428Sandreas.hansson@arm.com// After the scheduling, a sequence of commands are obtained and they are written
19810428Sandreas.hansson@arm.com// into commands.txt which will be used for power analysis.
19911555Sjungma@eit.uni-kl.devoid cmdScheduler::analyticalScheduling(const MemorySpecification& memSpec)
20010428Sandreas.hansson@arm.com{
20111555Sjungma@eit.uni-kl.de  int64_t  transType        = -1;
20211555Sjungma@eit.uni-kl.de  int64_t timer          = 0;
20311555Sjungma@eit.uni-kl.de  uint64_t  bankGroupPointer = 0;
20411555Sjungma@eit.uni-kl.de  uint64_t  bankGroupAddr    = 0;
20510428Sandreas.hansson@arm.com  bool collisionFound;
20610428Sandreas.hansson@arm.com  physicalAddr PhysicalAddress;
20710428Sandreas.hansson@arm.com  bool bankGroupSwitch  = false;
20811555Sjungma@eit.uni-kl.de  std::vector<uint64_t> bankPointer(static_cast<size_t>(nbrOfBankGroups), 0);
20911555Sjungma@eit.uni-kl.de  std::vector<int64_t>  bankAccessNum(static_cast<size_t>(nBanks), -1);
21011555Sjungma@eit.uni-kl.de  std::vector<bool> ACTSchedule(static_cast<size_t>(nBanks), false);
21111555Sjungma@eit.uni-kl.de  uint64_t bankAddr   = 0;
21211555Sjungma@eit.uni-kl.de  int64_t endTime     = 0;
21311555Sjungma@eit.uni-kl.de  int64_t tComing_REF = 0;
21410428Sandreas.hansson@arm.com
21510428Sandreas.hansson@arm.com  Inselfrefresh = 0;
21610428Sandreas.hansson@arm.com
21711555Sjungma@eit.uni-kl.de  const MemTimingSpec& memTimingSpec = memSpec.memTimingSpec;
21810428Sandreas.hansson@arm.com
21911555Sjungma@eit.uni-kl.de  for (uint64_t t = 0; t < transTrace.size(); t++) {
22010428Sandreas.hansson@arm.com    cmdScheduling.erase(cmdScheduling.begin(), cmdScheduling.end());
22110428Sandreas.hansson@arm.com
22211555Sjungma@eit.uni-kl.de    for (auto a : ACTSchedule) {
22311555Sjungma@eit.uni-kl.de      a = false;
22411555Sjungma@eit.uni-kl.de    }
22511555Sjungma@eit.uni-kl.de
22611555Sjungma@eit.uni-kl.de    for (auto& b : bankAccessNum) {
22711555Sjungma@eit.uni-kl.de      b = -1;
22810428Sandreas.hansson@arm.com    }
22910428Sandreas.hansson@arm.com
23010428Sandreas.hansson@arm.com    timingsGet      = false;
23110428Sandreas.hansson@arm.com    timer           = transTrace[t].timeStamp;
23210428Sandreas.hansson@arm.com
23310428Sandreas.hansson@arm.com    PhysicalAddress = memoryMap(transTrace[t], memSpec);
23410428Sandreas.hansson@arm.com
23511555Sjungma@eit.uni-kl.de    for (auto& b : bankPointer) {
23611555Sjungma@eit.uni-kl.de      b = PhysicalAddress.bankAddr; // the bank pointer per group.
23710428Sandreas.hansson@arm.com    }
23810428Sandreas.hansson@arm.com    bankGroupPointer = PhysicalAddress.bankGroupAddr;
23910428Sandreas.hansson@arm.com
24011555Sjungma@eit.uni-kl.de    endTime = max(transFinish.time, PRE[static_cast<size_t>(transFinish.bank)].time +
24111555Sjungma@eit.uni-kl.de                                    static_cast<int>(memTimingSpec.RP));
24210428Sandreas.hansson@arm.com
24310428Sandreas.hansson@arm.com    // Before starting the scheduling for the next transaction, it has to
24410428Sandreas.hansson@arm.com    // check whether it is necessary for implementing power down.
24510428Sandreas.hansson@arm.com    if (power_down == SELF_REFRESH)
24610428Sandreas.hansson@arm.com      pdScheduling(endTime, timer, memSpec);
24710428Sandreas.hansson@arm.com    else if (power_down == POWER_DOWN)
24810428Sandreas.hansson@arm.com      pdScheduling(endTime, min(timer, tREF), memSpec);
24910428Sandreas.hansson@arm.com
25010428Sandreas.hansson@arm.com    tComing_REF = tREF;
25110428Sandreas.hansson@arm.com
25210428Sandreas.hansson@arm.com    ///////////////Scheduling Refresh////////////////////////
25310428Sandreas.hansson@arm.com    if (((transFinish.time >= tREF) || (timer >= tREF))) {
25411555Sjungma@eit.uni-kl.de      for (int64_t i = 0; i <= ((timer - tComing_REF) > 0 ? (timer - tComing_REF) /
25510428Sandreas.hansson@arm.com                               memTimingSpec.REFI : 0); i++) {
25610428Sandreas.hansson@arm.com        cmd.bank = 0;
25710428Sandreas.hansson@arm.com        cmd.name = "REF";
25811555Sjungma@eit.uni-kl.de        cmd.time = max(max(max(transFinish.time, PRE[static_cast<size_t>(transFinish.bank)].time + memTimingSpec.RP), tREF), startTime);
25911555Sjungma@eit.uni-kl.de        if ((power_down == SELF_REFRESH && !Inselfrefresh) || power_down != SELF_REFRESH) {
26010428Sandreas.hansson@arm.com          cmdScheduling.push_back(cmd);
26110428Sandreas.hansson@arm.com          startTime = cmd.time + memTimingSpec.RFC;
26210428Sandreas.hansson@arm.com        }
26310428Sandreas.hansson@arm.com        tREF = tREF + memTimingSpec.REFI;
26410428Sandreas.hansson@arm.com        // during the refreshing, power down should be taken into account.
26510428Sandreas.hansson@arm.com        if (!Inselfrefresh)
26610428Sandreas.hansson@arm.com          pdScheduling(endTime, min(timer, tREF), memSpec);
26710428Sandreas.hansson@arm.com      }
26810428Sandreas.hansson@arm.com    }
26910428Sandreas.hansson@arm.com    ///////////////Execution Transactions///////////////////
27011555Sjungma@eit.uni-kl.de    uint64_t Bs = PhysicalAddress.bankAddr;
27110428Sandreas.hansson@arm.com    transType = transTrace[t].type;
27210428Sandreas.hansson@arm.com
27310428Sandreas.hansson@arm.com    tRWTP     = getRWTP(transType, memSpec);
27410428Sandreas.hansson@arm.com
27510428Sandreas.hansson@arm.com    for (int i = 0; i < BI; i++) {
27610428Sandreas.hansson@arm.com      for (int k = 0; k < BC; k++) {
27710428Sandreas.hansson@arm.com        if (memSpec.memoryType == MemoryType::DDR4) {
27810428Sandreas.hansson@arm.com          bankGroupPointer = PhysicalAddress.bankGroupAddr;
27910428Sandreas.hansson@arm.com        }
28010428Sandreas.hansson@arm.com
28110428Sandreas.hansson@arm.com        for (int j = 0; j < BGI; j++) {
28210428Sandreas.hansson@arm.com          bankGroupSwitch = false;
28310428Sandreas.hansson@arm.com          if (memSpec.memoryType == MemoryType::DDR4) {
28410428Sandreas.hansson@arm.com            if (bankGroupPointer != bankGroupAddr) {
28510428Sandreas.hansson@arm.com              bankGroupSwitch = true;
28610428Sandreas.hansson@arm.com            }
28710428Sandreas.hansson@arm.com            // update to the current bank group address.
28811555Sjungma@eit.uni-kl.de            bankGroupAddr = PhysicalAddress.bankGroupAddr + static_cast<uint64_t>(j);
28911555Sjungma@eit.uni-kl.de            bankAddr = bankGroupAddr * static_cast<uint64_t>(nBanks) / nbrOfBankGroups + bankPointer[bankGroupAddr];
29010428Sandreas.hansson@arm.com          } else   {
29110428Sandreas.hansson@arm.com            bankAddr = Bs + i;
29210428Sandreas.hansson@arm.com          }
29310428Sandreas.hansson@arm.com
29410428Sandreas.hansson@arm.com          if (!timingsGet) {
29510428Sandreas.hansson@arm.com            getTimingConstraints(bankGroupSwitch, memSpec,
29610428Sandreas.hansson@arm.com                                 PreRDWR.Type, transType);
29710428Sandreas.hansson@arm.com          }
29810428Sandreas.hansson@arm.com
29910428Sandreas.hansson@arm.com          ////////////////ACT Scheduling///////////////////
30010428Sandreas.hansson@arm.com          if (!ACTSchedule[bankAddr]) {
30110428Sandreas.hansson@arm.com            cmd.bank                  = bankAddr;
30210428Sandreas.hansson@arm.com            cmd.PhysicalAddr.bankAddr = cmd.bank;
30310428Sandreas.hansson@arm.com            cmd.PhysicalAddr.rowAddr  = PhysicalAddress.rowAddr;
30410428Sandreas.hansson@arm.com            cmd.Type                  = ACTIVATE;
30510428Sandreas.hansson@arm.com            cmd.name                  = "ACT";
30610428Sandreas.hansson@arm.com            Inselfrefresh             = 0;
30710428Sandreas.hansson@arm.com            cmd.time                  = max(max(ACT[bankaccess - 1].time + tRRD_init,
30810428Sandreas.hansson@arm.com                                                PRE[cmd.bank].time + static_cast<int>(memTimingSpec.RP)),
30910428Sandreas.hansson@arm.com                                            ACT[bankaccess - 4].time +
31010428Sandreas.hansson@arm.com                                            static_cast<int>(memTimingSpec.FAW));
31110428Sandreas.hansson@arm.com
31210428Sandreas.hansson@arm.com            if (memSpec.memoryType == MemoryType::WIDEIO_SDR) {
31310428Sandreas.hansson@arm.com              cmd.time = max(max(ACT[bankaccess - 1].time + tRRD_init,
31410428Sandreas.hansson@arm.com                                 PRE[cmd.bank].time + static_cast<int>(memTimingSpec.RP)),
31510428Sandreas.hansson@arm.com                             ACT[bankaccess - 2].time +
31610428Sandreas.hansson@arm.com                             static_cast<int>(memTimingSpec.TAW));
31710428Sandreas.hansson@arm.com            }
31810428Sandreas.hansson@arm.com
31911555Sjungma@eit.uni-kl.de            if (i == 0 && j == 0) {
32010428Sandreas.hansson@arm.com              cmd.time = max(cmd.time, PreRDWR.time + 1);
32110428Sandreas.hansson@arm.com              cmd.time = max(cmd.time, timer);
32210428Sandreas.hansson@arm.com              cmd.time = max(startTime, cmd.time);
32310428Sandreas.hansson@arm.com            }
32410428Sandreas.hansson@arm.com
32510428Sandreas.hansson@arm.com            //////////collision detection////////////////////
32610428Sandreas.hansson@arm.com            for (int n = 1; n <= i * BGI + j; n++) {
32710428Sandreas.hansson@arm.com              collisionFound = false;
32810428Sandreas.hansson@arm.com              for (unsigned m = 0; m < RDWR[bankaccess - n].size(); m++) {
32910428Sandreas.hansson@arm.com                if (RDWR[bankaccess - n][m].time == cmd.time) {
33010428Sandreas.hansson@arm.com                  cmd.time      += 1; // ACT is shifted
33110428Sandreas.hansson@arm.com                  collisionFound = true;
33210428Sandreas.hansson@arm.com                  break;
33310428Sandreas.hansson@arm.com                }
33410428Sandreas.hansson@arm.com              }
33510428Sandreas.hansson@arm.com              if (collisionFound) {
33610428Sandreas.hansson@arm.com                break;
33710428Sandreas.hansson@arm.com              }
33810428Sandreas.hansson@arm.com            }
33910428Sandreas.hansson@arm.com
34010428Sandreas.hansson@arm.com            ACT.push_back(cmd);
34110428Sandreas.hansson@arm.com            cmdScheduling.push_back(cmd);
34210428Sandreas.hansson@arm.com
34310428Sandreas.hansson@arm.com            ACTSchedule[bankAddr]   = true;
34410428Sandreas.hansson@arm.com            bankAccessNum[bankAddr] = bankaccess;
34510428Sandreas.hansson@arm.com            bankaccess++;
34610428Sandreas.hansson@arm.com          }
34710428Sandreas.hansson@arm.com
34810428Sandreas.hansson@arm.com          /////RDWR Scheduling//////
34910428Sandreas.hansson@arm.com          cmd.bank = bankAddr;
35010428Sandreas.hansson@arm.com          cmd.PhysicalAddr.bankAddr = cmd.bank;
35110428Sandreas.hansson@arm.com          cmd.PhysicalAddr.rowAddr  = PhysicalAddress.rowAddr;
35210428Sandreas.hansson@arm.com          cmd.PhysicalAddr.colAddr  = PhysicalAddress.colAddr + k * burstLength;
35310428Sandreas.hansson@arm.com          cmd.Type = transType;
35410428Sandreas.hansson@arm.com          switch (transType) {
35510428Sandreas.hansson@arm.com          case READ:
35610428Sandreas.hansson@arm.com            cmd.name = "RD";
35710428Sandreas.hansson@arm.com            break;
35810428Sandreas.hansson@arm.com
35910428Sandreas.hansson@arm.com          case WRITE:
36010428Sandreas.hansson@arm.com            cmd.name = "WR";
36110428Sandreas.hansson@arm.com            break;
36210428Sandreas.hansson@arm.com          }
36310428Sandreas.hansson@arm.com          for (int ACTBank = static_cast<int>(ACT.size() - 1);
36410428Sandreas.hansson@arm.com               ACTBank >= 0; ACTBank--) {
36511555Sjungma@eit.uni-kl.de            if (ACT[ACTBank].bank == static_cast<int64_t>(bankAddr)) {
36610428Sandreas.hansson@arm.com              cmd.time = max(PreRDWR.time + tSwitch_init, ACT.back().time
36710428Sandreas.hansson@arm.com                             + static_cast<int>(memTimingSpec.RCD));
36810428Sandreas.hansson@arm.com              break;
36910428Sandreas.hansson@arm.com            }
37010428Sandreas.hansson@arm.com          }
37110428Sandreas.hansson@arm.com
37210428Sandreas.hansson@arm.com          if ((i == BI - 1) && (k == BC - 1) && (j == BGI - 1)) {
37310428Sandreas.hansson@arm.com            transFinish.time = cmd.time + 1;
37410428Sandreas.hansson@arm.com            transFinish.bank = bankAddr;
37510428Sandreas.hansson@arm.com          }
37610428Sandreas.hansson@arm.com          if (k == BC - 1) {
37710428Sandreas.hansson@arm.com            switch (transType) {
37810428Sandreas.hansson@arm.com            case READ:
37910428Sandreas.hansson@arm.com              cmd.name = "RDA";
38010428Sandreas.hansson@arm.com              break;
38110428Sandreas.hansson@arm.com
38210428Sandreas.hansson@arm.com            case WRITE:
38310428Sandreas.hansson@arm.com              cmd.name = "WRA";
38410428Sandreas.hansson@arm.com              break;
38510428Sandreas.hansson@arm.com            }
38610428Sandreas.hansson@arm.com          }
38710428Sandreas.hansson@arm.com          PreRDWR = cmd;
38810428Sandreas.hansson@arm.com
38910428Sandreas.hansson@arm.com          RDWR[bankAccessNum[bankAddr]].push_back(cmd);
39010428Sandreas.hansson@arm.com          cmdScheduling.push_back(cmd);
39110428Sandreas.hansson@arm.com
39210428Sandreas.hansson@arm.com          ////////////////PRE Scheduling////////////////////
39310428Sandreas.hansson@arm.com          if (k == BC - 1) {
39410428Sandreas.hansson@arm.com            PRE[bankAddr].bank = bankAddr;
39510428Sandreas.hansson@arm.com            PRE[bankAddr].Type = PRECHARGE;
39610428Sandreas.hansson@arm.com            PRE[bankAddr].name = "PRE";
39710428Sandreas.hansson@arm.com            for (int ACTBank = static_cast<int>(ACT.size() - 1);
39810428Sandreas.hansson@arm.com                 ACTBank >= 0; ACTBank--) {
39911555Sjungma@eit.uni-kl.de              if (ACT[ACTBank].bank == static_cast<int64_t>(bankAddr)) {
40010428Sandreas.hansson@arm.com                PRE[bankAddr].time = max(ACT.back().time +
40110428Sandreas.hansson@arm.com                                         static_cast<int>(memTimingSpec.RAS),
40210428Sandreas.hansson@arm.com                                         PreRDWR.time + tRWTP);
40310428Sandreas.hansson@arm.com                break;
40410428Sandreas.hansson@arm.com              }
40510428Sandreas.hansson@arm.com            }
40610428Sandreas.hansson@arm.com            bankPointer[bankGroupAddr] = bankPointer[bankGroupAddr] + 1;
40710428Sandreas.hansson@arm.com          }
40810428Sandreas.hansson@arm.com
40910428Sandreas.hansson@arm.com          bankGroupPointer++;
41010428Sandreas.hansson@arm.com        }
41110428Sandreas.hansson@arm.com      }
41210428Sandreas.hansson@arm.com    }
41310428Sandreas.hansson@arm.com
41410428Sandreas.hansson@arm.com    // make sure the scheduled commands are stored with an ascending scheduling time
41510428Sandreas.hansson@arm.com    sort(cmdScheduling.begin(), cmdScheduling.end(),
41610428Sandreas.hansson@arm.com         commandItem::commandItemSorter());
41710428Sandreas.hansson@arm.com
41810428Sandreas.hansson@arm.com    // write the scheduled commands into commands.txt.
41910428Sandreas.hansson@arm.com    for (unsigned i = 0; i < cmdScheduling.size(); i++) {
42010428Sandreas.hansson@arm.com      cmdList.push_back(cmdScheduling[i]);
42110428Sandreas.hansson@arm.com    }
42210428Sandreas.hansson@arm.com
42310428Sandreas.hansson@arm.com    /////////////Update Vector Length/////////////////
42410428Sandreas.hansson@arm.com    // the vector length is reduced so that less memory is used for running
42510428Sandreas.hansson@arm.com    // this tool.
42611555Sjungma@eit.uni-kl.de    if (ACT.size() >= static_cast<size_t>(memSpec.memArchSpec.nbrOfBanks)) {
42710428Sandreas.hansson@arm.com      for (int m = 0; m < BI * BGI; m++) {
42810428Sandreas.hansson@arm.com        ACT.erase(ACT.begin());
42910428Sandreas.hansson@arm.com        RDWR[0].erase(RDWR[0].begin(), RDWR[0].end());
43010428Sandreas.hansson@arm.com        for (int h = 0; h < bankaccess - 1 - m; h++) {
43110428Sandreas.hansson@arm.com          RDWR[h].insert(RDWR[h].begin(), RDWR[h + 1].begin(), RDWR[h + 1].end());
43210428Sandreas.hansson@arm.com          RDWR[h + 1].resize(0);
43310428Sandreas.hansson@arm.com        }
43410428Sandreas.hansson@arm.com      }
43510428Sandreas.hansson@arm.com      bankaccess = bankaccess - (BI * BGI);
43610428Sandreas.hansson@arm.com    }
43710428Sandreas.hansson@arm.com  }
43810428Sandreas.hansson@arm.com
43910428Sandreas.hansson@arm.com  for (unsigned j = 0; j < cmdList.size(); j++) {
44010428Sandreas.hansson@arm.com    commands.precision(0);
44110428Sandreas.hansson@arm.com    commands << fixed << cmdList[j].time << "," << cmdList[j].name << "," <<
44210428Sandreas.hansson@arm.com      cmdList[j].bank << endl;
44310428Sandreas.hansson@arm.com  }
44410428Sandreas.hansson@arm.com  cmdList.erase(cmdList.begin(), cmdList.end());
44510428Sandreas.hansson@arm.com} // cmdScheduler::analyticalScheduling
44610428Sandreas.hansson@arm.com
44710428Sandreas.hansson@arm.com// to add the power down/up during the command scheduling for transactions.
44810428Sandreas.hansson@arm.com// It is called when the command scheduling for a transaction is finished, and it
44910428Sandreas.hansson@arm.com// is also called if there is a refresh.
45011555Sjungma@eit.uni-kl.devoid cmdScheduler::pdScheduling(int64_t endTime, int64_t timer,
45111555Sjungma@eit.uni-kl.de                                const MemorySpecification& memSpec)
45210428Sandreas.hansson@arm.com{
45311555Sjungma@eit.uni-kl.de  int64_t ZERO = 0;
45411555Sjungma@eit.uni-kl.de  const MemTimingSpec& memTimingSpec = memSpec.memTimingSpec;
45510428Sandreas.hansson@arm.com
45610428Sandreas.hansson@arm.com  endTime = max(endTime, startTime);
45711555Sjungma@eit.uni-kl.de  int64_t pdTime = max(ZERO, timer - endTime);
45810428Sandreas.hansson@arm.com
45910428Sandreas.hansson@arm.com  if ((timer > (endTime + memTimingSpec.CKE)) && (power_down == POWER_DOWN)) {
46010428Sandreas.hansson@arm.com    cmd.bank = 0;
46110428Sandreas.hansson@arm.com    cmd.name = "PDN_S_PRE";
46210428Sandreas.hansson@arm.com    cmd.time = endTime;
46310428Sandreas.hansson@arm.com    cmdScheduling.push_back(cmd);
46410428Sandreas.hansson@arm.com    cmd.name = "PUP_PRE";
46510428Sandreas.hansson@arm.com
46610428Sandreas.hansson@arm.com    if (pdTime > memTimingSpec.REFI)
46710428Sandreas.hansson@arm.com      cmd.time = cmd.time + memTimingSpec.REFI;
46810428Sandreas.hansson@arm.com    else
46910428Sandreas.hansson@arm.com      cmd.time = cmd.time + pdTime;
47010428Sandreas.hansson@arm.com
47110428Sandreas.hansson@arm.com    if (memSpec.memoryType.isLPDDRFamily())
47210428Sandreas.hansson@arm.com      startTime = cmd.time + memTimingSpec.XP;
47310428Sandreas.hansson@arm.com    else
47410428Sandreas.hansson@arm.com      startTime = cmd.time + memTimingSpec.XPDLL - memTimingSpec.RCD;
47510428Sandreas.hansson@arm.com
47610428Sandreas.hansson@arm.com    cmdScheduling.push_back(cmd);
47710428Sandreas.hansson@arm.com  } else if ((timer > (endTime + memTimingSpec.CKESR)) && (power_down == SELF_REFRESH))    {
47810428Sandreas.hansson@arm.com    cmd.bank      = 0;
47910428Sandreas.hansson@arm.com    cmd.name      = "SREN";
48010428Sandreas.hansson@arm.com    cmd.time      = endTime;
48110428Sandreas.hansson@arm.com    cmdScheduling.push_back(cmd);
48210428Sandreas.hansson@arm.com    Inselfrefresh = 1;
48310428Sandreas.hansson@arm.com    cmd.name      = "SREX";
48410428Sandreas.hansson@arm.com    cmd.time      = cmd.time + pdTime;
48510428Sandreas.hansson@arm.com
48610428Sandreas.hansson@arm.com    if (memSpec.memoryType.isLPDDRFamily())
48710428Sandreas.hansson@arm.com      startTime = cmd.time + memTimingSpec.XS;
48810428Sandreas.hansson@arm.com    else
48910428Sandreas.hansson@arm.com      startTime = cmd.time + memTimingSpec.XSDLL - memTimingSpec.RCD;
49010428Sandreas.hansson@arm.com
49110428Sandreas.hansson@arm.com    cmdScheduling.push_back(cmd);
49210428Sandreas.hansson@arm.com  }
49310428Sandreas.hansson@arm.com} // cmdScheduler::pdScheduling
49410428Sandreas.hansson@arm.com
49510428Sandreas.hansson@arm.com// get the time when a precharge occurs after a read/write command is scheduled.
49610428Sandreas.hansson@arm.com// In addition, it copes with different kind of memories.
49711555Sjungma@eit.uni-kl.deint64_t cmdScheduler::getRWTP(int64_t transType, const MemorySpecification& memSpec)
49810428Sandreas.hansson@arm.com{
49911555Sjungma@eit.uni-kl.de  int64_t tRWTP_init = 0;
50011555Sjungma@eit.uni-kl.de  const MemTimingSpec& memTimingSpec     = memSpec.memTimingSpec;
50111555Sjungma@eit.uni-kl.de  const MemArchitectureSpec& memArchSpec = memSpec.memArchSpec;
50210428Sandreas.hansson@arm.com
50310428Sandreas.hansson@arm.com  if (transType == READ) {
50410428Sandreas.hansson@arm.com    switch (memSpec.memoryType) {
50510428Sandreas.hansson@arm.com    case MemoryType::LPDDR:
50610428Sandreas.hansson@arm.com    case MemoryType::WIDEIO_SDR:
50710428Sandreas.hansson@arm.com      tRWTP_init = memArchSpec.burstLength / memArchSpec.dataRate;
50810428Sandreas.hansson@arm.com      break;
50910428Sandreas.hansson@arm.com
51010428Sandreas.hansson@arm.com    case MemoryType::LPDDR2:
51110428Sandreas.hansson@arm.com    case MemoryType::LPDDR3:
51210428Sandreas.hansson@arm.com      tRWTP_init = memArchSpec.burstLength / memArchSpec.dataRate +
51311555Sjungma@eit.uni-kl.de                   max(int64_t(0), memTimingSpec.RTP - 2);
51410428Sandreas.hansson@arm.com      break;
51510428Sandreas.hansson@arm.com
51610428Sandreas.hansson@arm.com    case MemoryType::DDR2:
51710428Sandreas.hansson@arm.com      tRWTP_init = memTimingSpec.AL + memArchSpec.burstLength /
51810428Sandreas.hansson@arm.com                   memArchSpec.dataRate +
51911555Sjungma@eit.uni-kl.de                   max(memTimingSpec.RTP, int64_t(2)) - 2;
52010428Sandreas.hansson@arm.com      break;
52110428Sandreas.hansson@arm.com
52210428Sandreas.hansson@arm.com    case MemoryType::DDR3:
52310428Sandreas.hansson@arm.com    case MemoryType::DDR4:
52410428Sandreas.hansson@arm.com      tRWTP_init = memTimingSpec.RTP;
52510428Sandreas.hansson@arm.com      break;
52610428Sandreas.hansson@arm.com    default:
52710428Sandreas.hansson@arm.com      assert("Unknown memory type" && false);
52810428Sandreas.hansson@arm.com    } // switch
52910428Sandreas.hansson@arm.com  } else if (transType == WRITE)    {
53010428Sandreas.hansson@arm.com    if (memSpec.memoryType == MemoryType::WIDEIO_SDR) {
53110428Sandreas.hansson@arm.com      tRWTP_init = memTimingSpec.WL + memArchSpec.burstLength /
53211555Sjungma@eit.uni-kl.de                   memArchSpec.dataRate - 1 + memTimingSpec.WR;
53310428Sandreas.hansson@arm.com    } else   {
53410428Sandreas.hansson@arm.com      tRWTP_init = memTimingSpec.WL + memArchSpec.burstLength /
53511555Sjungma@eit.uni-kl.de                   memArchSpec.dataRate + memTimingSpec.WR;
53610428Sandreas.hansson@arm.com    }
53710428Sandreas.hansson@arm.com    if ((memSpec.memoryType == MemoryType::LPDDR2) ||
53810428Sandreas.hansson@arm.com        (memSpec.memoryType == MemoryType::LPDDR3)) {
53910428Sandreas.hansson@arm.com      tRWTP_init = tRWTP_init + 1;
54010428Sandreas.hansson@arm.com    }
54110428Sandreas.hansson@arm.com  }
54210428Sandreas.hansson@arm.com
54310428Sandreas.hansson@arm.com  return tRWTP_init;
54410428Sandreas.hansson@arm.com} // cmdScheduler::getRWTP
54510428Sandreas.hansson@arm.com
54610428Sandreas.hansson@arm.com// get the timings for command scheduling according to different memories.
54710428Sandreas.hansson@arm.com// In particular, tSwitch_init is generally used to provide the timings for
54810428Sandreas.hansson@arm.com// scheduling a read/write command after a read/write command which have been
54910428Sandreas.hansson@arm.com// scheduled to any possible banks within any possible bank groups (DDR4).
55011555Sjungma@eit.uni-kl.devoid cmdScheduler::getTimingConstraints(bool BGSwitch, const MemorySpecification& memSpec,
55111555Sjungma@eit.uni-kl.de                                        int64_t PreType, int64_t CurrentType)
55210428Sandreas.hansson@arm.com{
55311555Sjungma@eit.uni-kl.de  const MemTimingSpec& memTimingSpec     = memSpec.memTimingSpec;
55411555Sjungma@eit.uni-kl.de  const MemArchitectureSpec& memArchSpec = memSpec.memArchSpec;
55510428Sandreas.hansson@arm.com
55610428Sandreas.hansson@arm.com  if (memSpec.memoryType != MemoryType::DDR4) {
55710428Sandreas.hansson@arm.com    tRRD_init = memTimingSpec.RRD;
55810428Sandreas.hansson@arm.com    if (PreType == CurrentType) {
55910428Sandreas.hansson@arm.com      tSwitch_init = memTimingSpec.CCD;
56010428Sandreas.hansson@arm.com      timingsGet   = true;
56110428Sandreas.hansson@arm.com    }
56210428Sandreas.hansson@arm.com
56310428Sandreas.hansson@arm.com    if ((PreType == WRITE) && (CurrentType == READ)) {
56410428Sandreas.hansson@arm.com      if (memSpec.memoryType == MemoryType::WIDEIO_SDR) {
56510428Sandreas.hansson@arm.com        tSwitch_init = memTimingSpec.WL + memArchSpec.burstLength /
56610428Sandreas.hansson@arm.com                       memArchSpec.dataRate - 1 + memTimingSpec.WTR;
56710428Sandreas.hansson@arm.com      } else   {
56810428Sandreas.hansson@arm.com        tSwitch_init = memTimingSpec.WL + memArchSpec.burstLength /
56910428Sandreas.hansson@arm.com                       memArchSpec.dataRate + memTimingSpec.WTR;
57010428Sandreas.hansson@arm.com      }
57110428Sandreas.hansson@arm.com
57210428Sandreas.hansson@arm.com      if ((memSpec.memoryType == MemoryType::LPDDR2) ||
57310428Sandreas.hansson@arm.com          (memSpec.memoryType == MemoryType::LPDDR3)) {
57410428Sandreas.hansson@arm.com        tSwitch_init = tSwitch_init + 1;
57510428Sandreas.hansson@arm.com      }
57610428Sandreas.hansson@arm.com    }
57710428Sandreas.hansson@arm.com  }
57810428Sandreas.hansson@arm.com
57910428Sandreas.hansson@arm.com  if (memSpec.memoryType == MemoryType::DDR4) {
58010428Sandreas.hansson@arm.com    if (BGSwitch) {
58110428Sandreas.hansson@arm.com      tCCD_init = memTimingSpec.CCD_S;
58210428Sandreas.hansson@arm.com      tRRD_init = memTimingSpec.RRD_S;
58310428Sandreas.hansson@arm.com      tWTR_init = memTimingSpec.WTR_S;
58410428Sandreas.hansson@arm.com    } else   {
58510428Sandreas.hansson@arm.com      tCCD_init = memTimingSpec.CCD_L;
58610428Sandreas.hansson@arm.com      tRRD_init = memTimingSpec.RRD_L;
58710428Sandreas.hansson@arm.com      tWTR_init = memTimingSpec.WTR_L;
58810428Sandreas.hansson@arm.com    }
58910428Sandreas.hansson@arm.com
59010428Sandreas.hansson@arm.com    if (PreType == CurrentType) {
59110428Sandreas.hansson@arm.com      tSwitch_init = tCCD_init;
59210428Sandreas.hansson@arm.com      timingsGet   = true;
59311555Sjungma@eit.uni-kl.de    } else if (PreType == WRITE && CurrentType == READ) {
59410428Sandreas.hansson@arm.com      tSwitch_init = memTimingSpec.WL + memArchSpec.burstLength /
59510428Sandreas.hansson@arm.com                     memArchSpec.dataRate + tWTR_init;
59610428Sandreas.hansson@arm.com    }
59710428Sandreas.hansson@arm.com  }
59810428Sandreas.hansson@arm.com
59910428Sandreas.hansson@arm.com  if ((PreType == READ) && (CurrentType == WRITE)) {
60010428Sandreas.hansson@arm.com    tSwitch_init = memTimingSpec.RL + memArchSpec.burstLength /
60110428Sandreas.hansson@arm.com                   memArchSpec.dataRate + 2 - memTimingSpec.WL;
60210428Sandreas.hansson@arm.com  }
60310428Sandreas.hansson@arm.com} // cmdScheduler::getTimingConstraints
60410428Sandreas.hansson@arm.com
60510428Sandreas.hansson@arm.com// The logical address of each transaction is translated into a physical address
60610428Sandreas.hansson@arm.com// which consists of bank group (for DDR4), bank, row and column addresses.
60710428Sandreas.hansson@arm.comcmdScheduler::physicalAddr cmdScheduler::memoryMap(trans               Trans,
60811555Sjungma@eit.uni-kl.de                                                   const MemorySpecification& memSpec)
60910428Sandreas.hansson@arm.com{
61011555Sjungma@eit.uni-kl.de  int64_t DecLogic;
61110428Sandreas.hansson@arm.com  physicalAddr PhysicalAddr;
61210428Sandreas.hansson@arm.com
61310428Sandreas.hansson@arm.com  DecLogic = Trans.logicalAddress;
61410428Sandreas.hansson@arm.com
61510428Sandreas.hansson@arm.com  // row-bank-column-BI-BC-BGI-BL
61611555Sjungma@eit.uni-kl.de  if (BGI > 1 && memSpec.memoryType == MemoryType::DDR4) {
61711555Sjungma@eit.uni-kl.de    uint64_t colBits   = uintLog2(nColumns);
61811555Sjungma@eit.uni-kl.de    uint64_t bankShift = colBits + ((BI > 1) ? uintLog2(BI) : 0)  + ((BGI > 1) ? uintLog2(BGI) : 0);
61911555Sjungma@eit.uni-kl.de    uint64_t bankMask  = (nBanks / (BI * nbrOfBankGroups) - 1) << bankShift;
62011555Sjungma@eit.uni-kl.de    uint64_t bankAddr  = (DecLogic & bankMask) >> (colBits + ((BGI > 1) ? uintLog2(BGI) : 0));
62110428Sandreas.hansson@arm.com    PhysicalAddr.bankAddr = bankAddr;
62210428Sandreas.hansson@arm.com
62311555Sjungma@eit.uni-kl.de    uint64_t bankGroupShift = uintLog2(burstLength);
62411555Sjungma@eit.uni-kl.de    uint64_t bankGroupMask  = (nbrOfBankGroups / BGI - 1) << bankGroupShift;
62511555Sjungma@eit.uni-kl.de    uint64_t bankGroupAddr  = (DecLogic & bankGroupMask) >> bankGroupShift;
62610428Sandreas.hansson@arm.com    PhysicalAddr.bankGroupAddr = bankGroupAddr;
62710428Sandreas.hansson@arm.com
62811555Sjungma@eit.uni-kl.de    uint64_t colShift       = uintLog2(BC * burstLength) +
62911555Sjungma@eit.uni-kl.de                                                    ((BI > 1) ? uintLog2(BI) : 0) + ((BGI > 1) ? uintLog2(BGI) : 0);
63011555Sjungma@eit.uni-kl.de    uint64_t colMask        = (nColumns / (BC * burstLength) - 1) << colShift;
63111555Sjungma@eit.uni-kl.de    uint64_t colAddr        = (DecLogic & colMask) >> (colShift - uintLog2(static_cast<uint64_t>(BC) * burstLength));
63210428Sandreas.hansson@arm.com    PhysicalAddr.colAddr = colAddr;
63310428Sandreas.hansson@arm.com  } else   {
63411555Sjungma@eit.uni-kl.de    uint64_t colBits   = uintLog2(nColumns);
63511555Sjungma@eit.uni-kl.de    uint64_t bankShift = colBits + ((BI > 1) ? uintLog2(BI) : 0);
63611555Sjungma@eit.uni-kl.de    uint64_t bankMask  = (nBanks / BI - 1) << bankShift;
63711555Sjungma@eit.uni-kl.de    uint64_t bankAddr  = (DecLogic & bankMask) >> colBits;
63810428Sandreas.hansson@arm.com    PhysicalAddr.bankAddr = bankAddr;
63910428Sandreas.hansson@arm.com
64011555Sjungma@eit.uni-kl.de    uint64_t colShift  = (uintLog2(BC * burstLength) + ((BI > 1) ? uintLog2(BI) : 0));
64111555Sjungma@eit.uni-kl.de    uint64_t colMask   = (nColumns / (BC * burstLength) - 1) << colShift;
64211555Sjungma@eit.uni-kl.de    uint64_t colAddr   = (DecLogic & colMask) >> (colShift - uintLog2(BC * burstLength));
64310428Sandreas.hansson@arm.com    PhysicalAddr.colAddr       = colAddr;
64410428Sandreas.hansson@arm.com
64510428Sandreas.hansson@arm.com    PhysicalAddr.bankGroupAddr = 0;
64610428Sandreas.hansson@arm.com  }
64710428Sandreas.hansson@arm.com
64811555Sjungma@eit.uni-kl.de  uint64_t rowShift = uintLog2(nColumns * nBanks);
64911555Sjungma@eit.uni-kl.de  uint64_t rowMask  = (memSpec.memArchSpec.nbrOfRows - 1) << rowShift;
65011555Sjungma@eit.uni-kl.de  uint64_t rowAddr  = (DecLogic & rowMask) >> rowShift;
65110428Sandreas.hansson@arm.com  PhysicalAddr.rowAddr = rowAddr;
65210428Sandreas.hansson@arm.com
65310428Sandreas.hansson@arm.com  return PhysicalAddr;
65410428Sandreas.hansson@arm.com} // cmdScheduler::memoryMap
65511555Sjungma@eit.uni-kl.de
65611555Sjungma@eit.uni-kl.deuint64_t cmdScheduler::uintLog2(uint64_t in)
65711555Sjungma@eit.uni-kl.de{
65811555Sjungma@eit.uni-kl.de  return static_cast<uint64_t>(log2(in));
65911555Sjungma@eit.uni-kl.de}