/*
 * Copyright (c) 2022, Technische Universität Kaiserslautern
 * All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions are
 * met:
 *
 * 1. Redistributions of source code must retain the above copyright notice,
 *    this list of conditions and the following disclaimer.
 *
 * 2. Redistributions in binary form must reproduce the above copyright
 *    notice, this list of conditions and the following disclaimer in the
 *    documentation and/or other materials provided with the distribution.
 *
 * 3. Neither the name of the copyright holder nor the names of its
 *    contributors may be used to endorse or promote products derived from
 *    this software without specific prior written permission.
 *
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
 * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER
 * OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
 * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
 * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
 * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 *
 * Authors:
 *    Iron Prando da Silva
 */

#include "TimeDependenciesInfoDDR5.h"
#include <cmath>

using namespace std;

TimeDependenciesInfoDDR5::TimeDependenciesInfoDDR5(const QJsonObject& memspec, const uint tCK) : DRAMTimeDependenciesBase(memspec, tCK) {
  mInitializeValues();

}

void TimeDependenciesInfoDDR5::rankIDToRankIDs(size_t rankID, size_t& dimmRID, size_t& physRID, size_t& logRID) const {
  logRID = rankID;
  physRID = logRID / mNumLogicalRanksPerPhysicalRank;
  dimmRID = physRID / mNumPhysicalRanksPerDIMMRank;
}

void TimeDependenciesInfoDDR5::bankIDToBankInGroup(size_t logicalRankID, size_t bankID, size_t& bankInGroup) const {
  bankInGroup = logicalRankID * mNumBanksPerGroup + bankID % mNumBanksPerGroup;

}

void TimeDependenciesInfoDDR5::mInitializeValues() {
  mNumOfRanks = mMemspecJson["memarchitecturespec"].toObject()["nbrOfRanks"].toInt();
  mNumOfDIMMRanks = mMemspecJson["memarchitecturespec"].toObject()["nbrOfDIMMRanks"].toInt();
  mNumPhysicalRanksPerDIMMRank = mMemspecJson["memarchitecturespec"].toObject()["nbrOfPhysicalRanks"].toInt();
  mNumLogicalRanksPerPhysicalRank = mMemspecJson["memarchitecturespec"].toObject()["nbrOfLogicalRanks"].toInt();

  mNumBanksPerGroup = mMemspecJson["memarchitecturespec"].toObject()["nbrOfBanks"].toInt(1);
  mNumBanksPerGroup /= mMemspecJson["memarchitecturespec"].toObject()["nbrOfBankGroups"].toInt(1);

  burstLength = mMemspecJson["memarchitecturespec"].toObject()["burstLength"].toInt();
  dataRate = mMemspecJson["memarchitecturespec"].toObject()["dataRate"].toInt();
  refMode = mMemspecJson["memarchitecturespec"].toObject()["refMode"].toInt();
  cmdMode = mMemspecJson["memarchitecturespec"].toObject()["cmdMode"].toInt();
  bitWidth = mMemspecJson["memarchitecturespec"].toObject()["width"].toInt();

  tRCD = tCK * mMemspecJson["memtimingspec"].toObject()["RCD"].toInt();
  tPPD = tCK * mMemspecJson["memtimingspec"].toObject()["PPD"].toInt();
  tRP = tCK * mMemspecJson["memtimingspec"].toObject()["RP"].toInt();
  tRAS = tCK * mMemspecJson["memtimingspec"].toObject()["RAS"].toInt();
  tRL = tCK * mMemspecJson["memtimingspec"].toObject()["RL"].toInt();
  RBL = tCK * mMemspecJson["memtimingspec"].toObject()["BL"].toInt();
  tRTP = tCK * mMemspecJson["memtimingspec"].toObject()["RTP"].toInt();
  tRPRE = tCK * mMemspecJson["memtimingspec"].toObject()["RPRE"].toInt();
  tRPST = tCK * mMemspecJson["memtimingspec"].toObject()["RPST"].toInt();
  tRDDQS = tCK * mMemspecJson["memtimingspec"].toObject()["RDDQS"].toInt();
  tWL = tCK * mMemspecJson["memtimingspec"].toObject()["WL"].toInt();
  WBL = tCK * mMemspecJson["memtimingspec"].toObject()["BL"].toInt();
  tWPRE = tCK * mMemspecJson["memtimingspec"].toObject()["WPRE"].toInt();
  tWPST = tCK * mMemspecJson["memtimingspec"].toObject()["WPST"].toInt();
  tWR = tCK * mMemspecJson["memtimingspec"].toObject()["WR"].toInt();
  tCCD_L_slr = tCK * mMemspecJson["memtimingspec"].toObject()["CCD_L_slr"].toInt();
  tCCD_L_WR_slr = tCK * mMemspecJson["memtimingspec"].toObject()["CCD_L_WR_slr"].toInt();
  tCCD_L_WR2_slr = tCK * mMemspecJson["memtimingspec"].toObject()["CCD_L_WR2_slr"].toInt();
  tCCD_S_slr = tCK * mMemspecJson["memtimingspec"].toObject()["CCD_S_slr"].toInt();
  tCCD_S_WR_slr = tCK * mMemspecJson["memtimingspec"].toObject()["CCD_S_WR_slr"].toInt();
  tCCD_dlr = tCK * mMemspecJson["memtimingspec"].toObject()["CCD_dlr"].toInt();
  tCCD_WR_dlr = tCK * mMemspecJson["memtimingspec"].toObject()["CCD_WR_dlr"].toInt();
  tCCD_WR_dpr = tCK * mMemspecJson["memtimingspec"].toObject()["CCD_WR_dpr"].toInt();
  tRRD_S_slr = tCK * mMemspecJson["memtimingspec"].toObject()["RRD_S_slr"].toInt();
  tRRD_L_slr = tCK * mMemspecJson["memtimingspec"].toObject()["RRD_L_slr"].toInt();
  tRRD_dlr = tCK * mMemspecJson["memtimingspec"].toObject()["RRD_dlr"].toInt();
  tFAW_slr = tCK * mMemspecJson["memtimingspec"].toObject()["FAW_slr"].toInt();
  tFAW_dlr = tCK * mMemspecJson["memtimingspec"].toObject()["FAW_dlr"].toInt();
  tWTR_L = tCK * mMemspecJson["memtimingspec"].toObject()["WTR_L"].toInt();
  tWTR_S = tCK * mMemspecJson["memtimingspec"].toObject()["WTR_S"].toInt();
  tRFC_slr = tCK * mMemspecJson["memtimingspec"].toObject()["RFC_slr"].toInt();
  tRFC_dlr = tCK * mMemspecJson["memtimingspec"].toObject()["RFC_dlr"].toInt();
  tRFC_dpr = tCK * mMemspecJson["memtimingspec"].toObject()["RFC_dpr"].toInt();
  tRFCsb_slr = tCK * mMemspecJson["memtimingspec"].toObject()["RFCsb_slr"].toInt();
  tRFCsb_dlr = tCK * mMemspecJson["memtimingspec"].toObject()["RFCsb_dlr"].toInt();
  tREFI = tCK * mMemspecJson["memtimingspec"].toObject()["REFI"].toInt();
  tREFSBRD_slr = tCK * mMemspecJson["memtimingspec"].toObject()["REFSBRD_slr"].toInt();
  tREFSBRD_dlr = tCK * mMemspecJson["memtimingspec"].toObject()["REFSBRD_dlr"].toInt();
  tRTRS = tCK * mMemspecJson["memtimingspec"].toObject()["RTRS"].toInt();
  UNKNOWN = tCK * mMemspecJson["memtimingspec"].toObject()["NKNOWN"].toInt();
  tCPDED = tCK * mMemspecJson["memtimingspec"].toObject()["CPDED"].toInt();
  tPD = tCK * mMemspecJson["memtimingspec"].toObject()["PD"].toInt();
  tXP = tCK * mMemspecJson["memtimingspec"].toObject()["XP"].toInt();
  tACTPDEN = tCK * mMemspecJson["memtimingspec"].toObject()["ACTPDEN"].toInt();
  tPRPDEN = tCK * mMemspecJson["memtimingspec"].toObject()["PRPDEN"].toInt();
  tREFPDEN = tCK * mMemspecJson["memtimingspec"].toObject()["REFPDEN"].toInt();

  tRC = tRAS + tRP;
  
  if (refMode == 1) {
    tRFC_slr = tCK * mMemspecJson["memtimingspec"].toObject()["RFC1_slr"].toInt();
    tRFC_dlr = tCK * mMemspecJson["memtimingspec"].toObject()["RFC1_dlr"].toInt();
    tRFC_dpr = tCK * mMemspecJson["memtimingspec"].toObject()["RFC1_dpr"].toInt();
    tREFI = tCK * mMemspecJson["memtimingspec"].toObject()["REFI1"].toInt();
  } else {
    tRFC_slr = tCK * mMemspecJson["memtimingspec"].toObject()["RFC2_slr"].toInt();
    tRFC_dlr = tCK * mMemspecJson["memtimingspec"].toObject()["RFC2_dlr"].toInt();
    tRFC_dpr = tCK * mMemspecJson["memtimingspec"].toObject()["RFC2_dpr"].toInt();
    tREFI = tCK * mMemspecJson["memtimingspec"].toObject()["REFI2"].toInt();
  }

  if (cmdMode == 2) {
    shortCmdOffset = 1 * tCK;
    longCmdOffset = 3 * tCK;
  } else {
    shortCmdOffset = 0 * tCK;
    longCmdOffset = 1 * tCK;
  }

  cmdLengthDiff = tCK * mMemspecJson["memarchitecturespec"].toObject()["cmdMode"].toInt();

  tBURST16 = 8 * tCK;
  tBURST32 = 16 * tCK;

  tRD_BURST = (uint) (RBL / (float) dataRate) * tCK;
  tWR_BURST = (uint) (WBL / (float) dataRate) * tCK;
  tWTRA = tWR - tRTP;
  tWRRDA = tWL + tBURST16 + tWTRA;
  tWRPRE = tWL + tBURST16 + tWR;
  tRDAACT = tRTP + tRP;
  tWRAACT = tWRPRE + tRP;
  tCCD_L_RTW_slr = tRL - tWL + tBURST16 + 2 * tCK - tRDDQS + tRPST + tWPRE;
  tCCD_S_RTW_slr = tRL - tWL + tBURST16 + 2 * tCK - tRDDQS + tRPST + tWPRE;
  tCCD_RTW_dlr = tRL - tWL + tBURST16 + 2 * tCK - tRDDQS + tRPST + tWPRE;
  tRDRD_dpr = tRD_BURST + tRTRS;
  tRDRD_ddr = tRD_BURST + tRTRS;
  tRDWR_dpr = tRL - tWL + tRD_BURST + tRTRS - tRDDQS + tRPST + tWPRE;
  tRDWR_ddr = tRL - tWL + tRD_BURST + tRTRS - tRDDQS + tRPST + tWPRE;
  tCCD_L_WTR_slr = tWL + tBURST16 + tWTR_L;
  tCCD_S_WTR_slr = tWL + tBURST16 + tWTR_S;
  tCCD_WTR_dlr = tWL + tBURST16 + tWTR_S;
  tWRWR_dpr = max(tCCD_WR_dpr, tBURST16 + tRTRS);
  tWRWR_ddr = tBURST16 + tRTRS;
  tWRRD_dpr = tWL - tRL + tBURST16 + tRTRS + tRDDQS + tWPST + tRPRE;
  tWRRD_ddr = tWL - tRL + tBURST16 + tRTRS + tRDDQS + tWPST + tRPRE;
  tRDPDEN = tRL + tBURST16 + cmdLengthDiff;
  tWRPDEN = tWL + tBURST16 + tWR + cmdLengthDiff;
  tWRAPDEN = tWL + tBURST16 + tWR + cmdLengthDiff;

  mPools.insert({
    "CMD_BUS", {
      1, {
        {"ACT", 2 * tCK},
        {"RD", 2 * tCK},
        {"WR", 2 * tCK},
        {"RDA", 2 * tCK},
        {"WRA", 2 * tCK},
        {"PREPB", tCK},
        {"PREAB", tCK},
        {"REFAB", tCK},
        {"PRESB", tCK},
        {"RFMAB", tCK},
        {"REFSB", tCK},
        {"RFMSB", tCK},
      }
    }
  });

  mPools.insert({
    "FAW_LOGICAL", {
      4, {
        {"ACT", tFAW_slr - longCmdOffset},
        {"REFSB", tFAW_slr - shortCmdOffset},
        {"RFMSB", tFAW_slr - shortCmdOffset},
      }
    }
  });

  mPools.insert({
    "FAW_PHYSICAL", {
      4, {
        {"ACT", tFAW_dlr - longCmdOffset},
        {"REFSB", tFAW_dlr - shortCmdOffset},
        {"RFMSB", tFAW_dlr - shortCmdOffset},
      }
    }
  });

}

const std::vector<QString> TimeDependenciesInfoDDR5::getPossiblePhases() {
  return {
    "ACT",
    "RD",
    "WR",
    "PRESB",
    "PREPB",
    "RDA",
    "WRA",
    "RFMAB",
    "REFSB",
    "RFMSB",
    "REFAB",
    "PREAB",
    "PDEP",
    "PDXP",
    "SREFEN",
    "SREFEX",
    "PDEA",
    "PDXA",
  };
}

DependencyMap TimeDependenciesInfoDDR5::mSpecializedGetDependencies() const {
  DependencyMap dmap;

  auto passBurstLength16 = std::make_shared<PassFunction>(
    [] PASSFUNCTIONDECL {
      auto other = std::dynamic_pointer_cast<DDR5DBPhaseEntry>(otherPhase);
      if (!other) return false;
      return other->tBurstLength == 16;
    }
  );
  auto passBurstLength32 = std::make_shared<PassFunction>(
    [] PASSFUNCTIONDECL {
      auto other = std::dynamic_pointer_cast<DDR5DBPhaseEntry>(otherPhase);
      if (!other) return false;
      return other->tBurstLength == 32;
    }
  );
  const auto localBitWidth = bitWidth;
  auto passThisBL16AndBW4 = std::make_shared<PassFunction>(
    [localBitWidth] PASSFUNCTIONDECL {
      auto thisP = std::dynamic_pointer_cast<DDR5DBPhaseEntry>(thisPhase);
      if (!thisP) return false;
      return thisP->tBurstLength == 16 && localBitWidth == 4;
    }
  );
  auto passOtherBL32ThisBL16BW4 = std::make_shared<PassFunction>(
    [passBurstLength32, passThisBL16AndBW4] PASSFUNCTIONDECL {
      return passBurstLength32->execute(thisPhase, otherPhase) && passThisBL16AndBW4->execute(thisPhase, otherPhase);
    }
  );
  auto passOtherBL32ThisNotBL16BW4 = std::make_shared<PassFunction>(
    [passBurstLength32, passThisBL16AndBW4] PASSFUNCTIONDECL {
      return passBurstLength32->execute(thisPhase, otherPhase) && !passThisBL16AndBW4->execute(thisPhase, otherPhase);
    }
  );
  auto passOtherBL16ThisBL16BW4 = std::make_shared<PassFunction>(
    [passBurstLength16, passThisBL16AndBW4] PASSFUNCTIONDECL {
      return passBurstLength16->execute(thisPhase, otherPhase) && passThisBL16AndBW4->execute(thisPhase, otherPhase);
    }
  );
  auto passOtherBL16ThisNotBL16BW4 = std::make_shared<PassFunction>(
    [passBurstLength16, passThisBL16AndBW4] PASSFUNCTIONDECL {
      return passBurstLength16->execute(thisPhase, otherPhase) && !passThisBL16AndBW4->execute(thisPhase, otherPhase);
    }
  );

  dmap.emplace(
    piecewise_construct,
    forward_as_tuple("ACT"),
    forward_as_tuple(
      initializer_list<TimeDependency>{
        {tRC, "ACT", DependencyType::IntraBank, "tRC"},
        {tRRD_L_slr, "ACT", DependencyType::IntraBankGroup, "tRRD_L_slr"},
        {tRRD_S_slr, "ACT", DependencyType::IntraLogicalRank, "tRRD_S_slr"},
        {tRRD_dlr, "ACT", DependencyType::IntraPhysicalRank, "tRRD_dlr"},
        {tRDAACT, "RDA", DependencyType::IntraBank, "tRDAACT"},
        {tWRAACT, "WRA", DependencyType::IntraBank, "tWRAACT", passBurstLength16},
        {tWRAACT + tBURST16, "WRA", DependencyType::IntraBank, "tWRAACT + tBURST16", passBurstLength32},
        {tRP - cmdLengthDiff, "PREPB", DependencyType::IntraBank, "tRP - tCK"},
        {tRP - cmdLengthDiff, "PRESB", DependencyType::IntraBankInGroup, "tRP - tCK"},
        {tRP - cmdLengthDiff, "PREAB", DependencyType::IntraLogicalRank, "tRP - tCK"},
        {tRFC_slr - cmdLengthDiff, "REFAB", DependencyType::IntraLogicalRank, "tRFC_slr - tCK"},
        {tRFC_slr - cmdLengthDiff, "RFMAB", DependencyType::IntraLogicalRank, "tRFC_slr - tCK"},
        {tRFCsb_slr - cmdLengthDiff, "REFSB", DependencyType::IntraBankInGroup, "tRFCsb_slr - tCK"},
        {tREFSBRD_slr - cmdLengthDiff, "REFSB", DependencyType::IntraLogicalRank, "tREFSBRD_slr - tCK"},
        {tREFSBRD_dlr - cmdLengthDiff, "REFSB", DependencyType::IntraPhysicalRank, "tREFSBRD_dlr - tCK"},
        {tRFCsb_slr - cmdLengthDiff, "RFMSB", DependencyType::IntraBankInGroup, "tRFCsb_slr - tCK"},
        {tREFSBRD_slr - cmdLengthDiff, "RFMSB", DependencyType::IntraLogicalRank, "tREFSBRD_slr - tCK"},
        {tREFSBRD_dlr - cmdLengthDiff, "RFMSB", DependencyType::IntraPhysicalRank, "tREFSBRD_dlr - tCK"},
        {2 * tCK, "CMD_BUS", DependencyType::InterDIMMRank, "CommandBus"},
        {tFAW_slr - longCmdOffset, "FAW_LOGICAL", DependencyType::IntraLogicalRank, "tFAW_slr"},
        {tFAW_dlr - longCmdOffset, "FAW_PHYSICAL", DependencyType::IntraPhysicalRank, "tFAW_dlr"},
      }
    )
  );

  dmap.emplace(
    piecewise_construct,
    forward_as_tuple("RD"),
    forward_as_tuple(
      initializer_list<TimeDependency>{
        {tRCD, "ACT", DependencyType::IntraBank, "tRCD"},
        {tCCD_L_slr, "RD", DependencyType::IntraBankGroup, "tCCD_L_slr"},
        {tCCD_S_slr, "RD", DependencyType::IntraLogicalRank, "tCCD_S_slr"},
        {tCCD_dlr, "RD", DependencyType::IntraPhysicalRank, "tCCD_dlr", passBurstLength16},
        {tBURST32, "RD", DependencyType::IntraPhysicalRank, "tBURST32", passBurstLength32},
        {tRDRD_dpr, "RD", DependencyType::IntraDIMMRank, "tRDRD_dpr", passBurstLength16},
        {tRDRD_dpr + tBURST16, "RD", DependencyType::IntraDIMMRank, "tRDRD_dpr + tBURST16", passBurstLength32},
        {tRDRD_ddr, "RD", DependencyType::InterDIMMRank, "tRDRD_ddr", passBurstLength16},
        {tRDRD_ddr + tBURST16, "RD", DependencyType::InterDIMMRank, "tRDRD_ddr + tBURST16", passBurstLength32},
        {tCCD_L_slr, "RDA", DependencyType::IntraBankGroup, "tCCD_L_slr"},
        {tCCD_S_slr, "RDA", DependencyType::IntraLogicalRank, "tCCD_S_slr"},
        {tCCD_dlr, "RDA", DependencyType::IntraPhysicalRank, "tCCD_dlr", passBurstLength16},
        {tBURST32, "RDA", DependencyType::IntraPhysicalRank, "tBURST32", passBurstLength32},
        {tRDRD_dpr, "RDA", DependencyType::IntraDIMMRank, "tRDRD_dpr", passBurstLength16},
        {tRDRD_dpr + tBURST16, "RDA", DependencyType::IntraDIMMRank, "tRDRD_dpr + tBURST16", passBurstLength32},
        {tRDRD_ddr, "RDA", DependencyType::InterDIMMRank, "tRDRD_ddr", passBurstLength16},
        {tRDRD_ddr + tBURST16, "RDA", DependencyType::InterDIMMRank, "tRDRD_ddr + tBURST16", passBurstLength32},
        {tCCD_L_WTR_slr, "WR", DependencyType::IntraBankGroup, "tCCD_L_WTR_slr", passBurstLength16},
        {tCCD_L_WTR_slr + tBURST16, "WR", DependencyType::IntraBankGroup, "tCCD_L_WTR_slr + tBURST16", passBurstLength32},
        {tCCD_S_WTR_slr, "WR", DependencyType::IntraLogicalRank, "tCCD_S_WTR_slr", passBurstLength16},
        {tCCD_S_WTR_slr + tBURST16, "WR", DependencyType::IntraLogicalRank, "tCCD_S_WTR_slr + tBURST16", passBurstLength32},
        {tCCD_WTR_dlr, "WR", DependencyType::IntraPhysicalRank, "tCCD_WTR_dlr", passBurstLength16},
        {tCCD_WTR_dlr + tBURST16, "WR", DependencyType::IntraPhysicalRank, "tCCD_WTR_dlr + tBURST16", passBurstLength32},
        {tWRRD_dpr, "WR", DependencyType::IntraDIMMRank, "tWRRD_dpr", passBurstLength16},
        {tWRRD_dpr + tBURST16, "WR", DependencyType::IntraDIMMRank, "tWRRD_dpr + tBURST16", passBurstLength32},
        {tWRRD_ddr, "WR", DependencyType::InterDIMMRank, "tWRRD_ddr", passBurstLength16},
        {tWRRD_ddr + tBURST16, "WR", DependencyType::InterDIMMRank, "tWRRD_ddr + tBURST16", passBurstLength32},
        {tCCD_L_WTR_slr, "WRA", DependencyType::IntraBankGroup, "tCCD_L_WTR_slr", passBurstLength16},
        {tCCD_L_WTR_slr + tBURST16, "WRA", DependencyType::IntraBankGroup, "tCCD_L_WTR_slr + tBURST16", passBurstLength32},
        {tCCD_S_WTR_slr, "WRA", DependencyType::IntraLogicalRank, "tCCD_S_WTR_slr", passBurstLength16},
        {tCCD_S_WTR_slr + tBURST16, "WRA", DependencyType::IntraLogicalRank, "tCCD_S_WTR_slr + tBURST16", passBurstLength32},
        {tCCD_WTR_dlr, "WRA", DependencyType::IntraPhysicalRank, "tCCD_WTR_dlr", passBurstLength16},
        {tCCD_WTR_dlr + tBURST16, "WRA", DependencyType::IntraPhysicalRank, "tCCD_WTR_dlr + tBURST16", passBurstLength32},
        {tWRRD_dpr, "WRA", DependencyType::IntraDIMMRank, "tWRRD_dpr", passBurstLength16},
        {tWRRD_dpr + tBURST16, "WRA", DependencyType::IntraDIMMRank, "tWRRD_dpr + tBURST16", passBurstLength32},
        {tWRRD_ddr, "WRA", DependencyType::InterDIMMRank, "tWRRD_ddr", passBurstLength16},
        {tWRRD_ddr + tBURST16, "WRA", DependencyType::InterDIMMRank, "tWRRD_ddr + tBURST16", passBurstLength32},
        {2 * tCK, "CMD_BUS", DependencyType::InterDIMMRank, "CommandBus"},
      }
    )
  );

  dmap.emplace(
    piecewise_construct,
    forward_as_tuple("WR"),
    forward_as_tuple(
      initializer_list<TimeDependency>{
        {tRCD, "ACT", DependencyType::IntraBank, "tRCD"},
        {tCCD_L_RTW_slr, "RD", DependencyType::IntraBankGroup, "tCCD_L_RTW_slr", passBurstLength16},
        {tCCD_L_RTW_slr + tBURST16, "RD", DependencyType::IntraBankGroup, "tCCD_L_RTW_slr + tBURST16", passBurstLength32},
        {tCCD_S_RTW_slr, "RD", DependencyType::IntraLogicalRank, "tCCD_S_RTW_slr", passBurstLength16},
        {tCCD_S_RTW_slr + tBURST16, "RD", DependencyType::IntraLogicalRank, "tCCD_S_RTW_slr + tBURST16", passBurstLength32},
        {tCCD_RTW_dlr, "RD", DependencyType::IntraPhysicalRank, "tCCD_RTW_dlr", passBurstLength16},
        {tCCD_RTW_dlr + tBURST16, "RD", DependencyType::IntraPhysicalRank, "tCCD_RTW_dlr + tBURST16", passBurstLength32},
        {tRDWR_dpr, "RD", DependencyType::IntraDIMMRank, "tRDWR_dpr", passBurstLength16},
        {tRDWR_dpr + tBURST16, "RD", DependencyType::IntraDIMMRank, "tRDWR_dpr + tBURST16", passBurstLength32},
        {tRDWR_ddr, "RD", DependencyType::InterDIMMRank, "tRDWR_ddr", passBurstLength16},
        {tRDWR_ddr + tBURST16, "RD", DependencyType::InterDIMMRank, "tRDWR_ddr + tBURST16", passBurstLength32},
        {tCCD_L_RTW_slr, "RDA", DependencyType::IntraBankGroup, "tCCD_L_RTW_slr", passBurstLength16},
        {tCCD_L_RTW_slr + tBURST16, "RDA", DependencyType::IntraBankGroup, "tCCD_L_RTW_slr + tBURST16", passBurstLength32},
        {tCCD_S_RTW_slr, "RDA", DependencyType::IntraLogicalRank, "tCCD_S_RTW_slr", passBurstLength16},
        {tCCD_S_RTW_slr + tBURST16, "RDA", DependencyType::IntraLogicalRank, "tCCD_S_RTW_slr + tBURST16", passBurstLength32},
        {tCCD_RTW_dlr, "RDA", DependencyType::IntraPhysicalRank, "tCCD_RTW_dlr", passBurstLength16},
        {tCCD_RTW_dlr + tBURST16, "RDA", DependencyType::IntraPhysicalRank, "tCCD_RTW_dlr + tBURST16", passBurstLength32},
        {tRDWR_dpr, "RDA", DependencyType::IntraDIMMRank, "tRDWR_dpr", passBurstLength16},
        {tRDWR_dpr + tBURST16, "RDA", DependencyType::IntraDIMMRank, "tRDWR_dpr + tBURST16", passBurstLength32},
        {tRDWR_ddr, "RDA", DependencyType::InterDIMMRank, "tRDWR_ddr", passBurstLength16},
        {tRDWR_ddr + tBURST16, "RDA", DependencyType::InterDIMMRank, "tRDWR_ddr + tBURST16", passBurstLength32},
        {tCCD_L_WR_slr, "WR", DependencyType::IntraBankGroup, "tCCD_L_WR_slr", passOtherBL16ThisBL16BW4},
        {tCCD_L_WR_slr + tBURST16, "WR", DependencyType::IntraBankGroup, "tCCD_L_WR_slr + tBURST16", passOtherBL32ThisBL16BW4},
        {tCCD_L_WR2_slr, "WR", DependencyType::IntraBankGroup, "tCCD_L_WR2_slr", passOtherBL16ThisNotBL16BW4},
        {tCCD_L_WR2_slr + tBURST16, "WR", DependencyType::IntraBankGroup, "tCCD_L_WR2_slr + tBURST16", passOtherBL32ThisNotBL16BW4},
        {tCCD_S_WR_slr, "WR", DependencyType::IntraLogicalRank, "tCCD_S_WR_slr"},
        {tCCD_WR_dlr, "WR", DependencyType::IntraPhysicalRank, "tCCD_WR_dlr", passBurstLength16},
        {tBURST32, "WR", DependencyType::IntraPhysicalRank, "tBURST32", passBurstLength32},
        {tWRWR_dpr, "WR", DependencyType::IntraDIMMRank, "tWRWR_dpr", passBurstLength16},
        {tWRWR_dpr + tBURST16, "WR", DependencyType::IntraDIMMRank, "tWRWR_dpr + tBURST16", passBurstLength32},
        {tWRWR_ddr, "WR", DependencyType::InterDIMMRank, "tWRWR_ddr", passBurstLength16},
        {tWRWR_ddr + tBURST16, "WR", DependencyType::InterDIMMRank, "tWRWR_ddr + tBURST16", passBurstLength32},
        {tCCD_L_WR_slr, "WRA", DependencyType::IntraBankGroup, "tCCD_L_WR_slr", passOtherBL16ThisBL16BW4},
        {tCCD_L_WR_slr + tBURST16, "WRA", DependencyType::IntraBankGroup, "tCCD_L_WR_slr + tBURST16", passOtherBL32ThisBL16BW4},
        {tCCD_L_WR2_slr, "WRA", DependencyType::IntraBankGroup, "tCCD_L_WR2_slr", passOtherBL16ThisNotBL16BW4},
        {tCCD_L_WR2_slr + tBURST16, "WRA", DependencyType::IntraBankGroup, "tCCD_L_WR2_slr + tBURST16", passOtherBL32ThisNotBL16BW4},
        {tCCD_S_WR_slr, "WRA", DependencyType::IntraLogicalRank, "tCCD_S_WR_slr"},
        {tCCD_WR_dlr, "WRA", DependencyType::IntraPhysicalRank, "tCCD_WR_dlr", passBurstLength16},
        {tBURST32, "WRA", DependencyType::IntraPhysicalRank, "tBURST32", passBurstLength32},
        {tWRWR_dpr, "WRA", DependencyType::IntraDIMMRank, "tWRWR_dpr", passBurstLength16},
        {tWRWR_dpr + tBURST16, "WRA", DependencyType::IntraDIMMRank, "tWRWR_dpr + tBURST16", passBurstLength32},
        {tWRWR_ddr, "WRA", DependencyType::InterDIMMRank, "tWRWR_ddr", passBurstLength16},
        {tWRWR_ddr + tBURST16, "WRA", DependencyType::InterDIMMRank, "tWRWR_ddr + tBURST16", passBurstLength32},
        {2 * tCK, "CMD_BUS", DependencyType::InterDIMMRank, "CommandBus"},
      }
    )
  );

  dmap.emplace(
    piecewise_construct,
    forward_as_tuple("PREPB"),
    forward_as_tuple(
      initializer_list<TimeDependency>{
        {tRAS + cmdLengthDiff, "ACT", DependencyType::IntraBank, "tRAS + tCK"},
        {tRTP + cmdLengthDiff, "RD", DependencyType::IntraBank, "tRTP + tCK"},
        {tWRPRE + cmdLengthDiff, "WR", DependencyType::IntraBank, "tWRPRE + tCK", passBurstLength16},
        {tWRPRE + cmdLengthDiff + tBURST16, "WR", DependencyType::IntraBank, "tWRPRE + tCK + tBURST16", passBurstLength32},
        {tPPD, "PREPB", DependencyType::IntraPhysicalRank, "tPPD"},
        {tPPD, "PREAB", DependencyType::IntraPhysicalRank, "tPPD"},
        {tPPD, "PRESB", DependencyType::IntraPhysicalRank, "tPPD"},
        {tCK, "CMD_BUS", DependencyType::InterDIMMRank, "CommandBus"},
      }
    )
  );

  dmap.emplace(
    piecewise_construct,
    forward_as_tuple("RDA"),
    forward_as_tuple(
      initializer_list<TimeDependency>{
        {tRCD, "ACT", DependencyType::IntraBank, "tRCD"},
        {tCCD_L_slr, "RD", DependencyType::IntraBankGroup, "tCCD_L_slr"},
        {tCCD_S_slr, "RD", DependencyType::IntraLogicalRank, "tCCD_S_slr"},
        {tCCD_dlr, "RD", DependencyType::IntraPhysicalRank, "tCCD_dlr", passBurstLength16},
        {tBURST32, "RD", DependencyType::IntraPhysicalRank, "tBURST32", passBurstLength32},
        {tRDRD_dpr, "RD", DependencyType::IntraDIMMRank, "tRDRD_dpr", passBurstLength16},
        {tRDRD_dpr + tBURST16, "RD", DependencyType::IntraDIMMRank, "tRDRD_dpr + tBURST16", passBurstLength32},
        {tRDRD_ddr, "RD", DependencyType::InterDIMMRank, "tRDRD_ddr", passBurstLength16},
        {tRDRD_ddr + tBURST16, "RD", DependencyType::InterDIMMRank, "tRDRD_ddr + tBURST16", passBurstLength32},
        {tCCD_L_slr, "RDA", DependencyType::IntraBankGroup, "tCCD_L_slr"},
        {tCCD_S_slr, "RDA", DependencyType::IntraLogicalRank, "tCCD_S_slr"},
        {tCCD_dlr, "RDA", DependencyType::IntraPhysicalRank, "tCCD_dlr", passBurstLength16},
        {tBURST32, "RDA", DependencyType::IntraPhysicalRank, "tBURST32", passBurstLength32},
        {tRDRD_dpr, "RDA", DependencyType::IntraDIMMRank, "tRDRD_dpr", passBurstLength16},
        {tRDRD_dpr + tBURST16, "RDA", DependencyType::IntraDIMMRank, "tRDRD_dpr + tBURST16", passBurstLength32},
        {tRDRD_ddr, "RDA", DependencyType::InterDIMMRank, "tRDRD_ddr", passBurstLength16},
        {tRDRD_ddr + tBURST16, "RDA", DependencyType::InterDIMMRank, "tRDRD_ddr + tBURST16", passBurstLength32},
        {tWRRDA, "WR", DependencyType::IntraBank, "tWRRDA", passBurstLength16},
        {tWRRDA + tBURST16, "WR", DependencyType::IntraBank, "tWRRDA + tBURST16", passBurstLength32},
        {tCCD_L_WTR_slr, "WR", DependencyType::IntraBankGroup, "tCCD_L_WTR_slr", passBurstLength16},
        {tCCD_L_WTR_slr + tBURST16, "WR", DependencyType::IntraBankGroup, "tCCD_L_WTR_slr + tBURST16", passBurstLength32},
        {tCCD_S_WTR_slr, "WR", DependencyType::IntraLogicalRank, "tCCD_S_WTR_slr", passBurstLength16},
        {tCCD_S_WTR_slr + tBURST16, "WR", DependencyType::IntraLogicalRank, "tCCD_S_WTR_slr + tBURST16", passBurstLength32},
        {tCCD_WTR_dlr, "WR", DependencyType::IntraPhysicalRank, "tCCD_WTR_dlr", passBurstLength16},
        {tCCD_WTR_dlr + tBURST16, "WR", DependencyType::IntraPhysicalRank, "tCCD_WTR_dlr + tBURST16", passBurstLength32},
        {tWRRD_dpr, "WR", DependencyType::IntraDIMMRank, "tWRRD_dpr", passBurstLength16},
        {tWRRD_dpr + tBURST16, "WR", DependencyType::IntraDIMMRank, "tWRRD_dpr + tBURST16", passBurstLength32},
        {tWRRD_ddr, "WR", DependencyType::InterDIMMRank, "tWRRD_ddr", passBurstLength16},
        {tWRRD_ddr + tBURST16, "WR", DependencyType::InterDIMMRank, "tWRRD_ddr + tBURST16", passBurstLength32},
        {tCCD_L_WTR_slr, "WRA", DependencyType::IntraBankGroup, "tCCD_L_WTR_slr", passBurstLength16},
        {tCCD_L_WTR_slr + tBURST16, "WRA", DependencyType::IntraBankGroup, "tCCD_L_WTR_slr + tBURST16", passBurstLength32},
        {tCCD_S_WTR_slr, "WRA", DependencyType::IntraLogicalRank, "tCCD_S_WTR_slr", passBurstLength16},
        {tCCD_S_WTR_slr + tBURST16, "WRA", DependencyType::IntraLogicalRank, "tCCD_S_WTR_slr + tBURST16", passBurstLength32},
        {tCCD_WTR_dlr, "WRA", DependencyType::IntraPhysicalRank, "tCCD_WTR_dlr", passBurstLength16},
        {tCCD_WTR_dlr + tBURST16, "WRA", DependencyType::IntraPhysicalRank, "tCCD_WTR_dlr + tBURST16", passBurstLength32},
        {tWRRD_dpr, "WRA", DependencyType::IntraDIMMRank, "tWRRD_dpr", passBurstLength16},
        {tWRRD_dpr + tBURST16, "WRA", DependencyType::IntraDIMMRank, "tWRRD_dpr + tBURST16", passBurstLength32},
        {tWRRD_ddr, "WRA", DependencyType::InterDIMMRank, "tWRRD_ddr", passBurstLength16},
        {tWRRD_ddr + tBURST16, "WRA", DependencyType::InterDIMMRank, "tWRRD_ddr + tBURST16", passBurstLength32},
        {2 * tCK, "CMD_BUS", DependencyType::InterDIMMRank, "CommandBus"},
      }
    )
  );

  dmap.emplace(
    piecewise_construct,
    forward_as_tuple("WRA"),
    forward_as_tuple(
      initializer_list<TimeDependency>{
        {tRCD, "ACT", DependencyType::IntraBank, "tRCD"},
        {tCCD_L_RTW_slr, "RD", DependencyType::IntraBankGroup, "tCCD_L_RTW_slr", passBurstLength16},
        {tCCD_L_RTW_slr + tBURST16, "RD", DependencyType::IntraBankGroup, "tCCD_L_RTW_slr + tBURST16", passBurstLength32},
        {tCCD_S_RTW_slr, "RD", DependencyType::IntraLogicalRank, "tCCD_S_RTW_slr", passBurstLength16},
        {tCCD_S_RTW_slr + tBURST16, "RD", DependencyType::IntraLogicalRank, "tCCD_S_RTW_slr + tBURST16", passBurstLength32},
        {tCCD_RTW_dlr, "RD", DependencyType::IntraPhysicalRank, "tCCD_RTW_dlr", passBurstLength16},
        {tCCD_RTW_dlr + tBURST16, "RD", DependencyType::IntraPhysicalRank, "tCCD_RTW_dlr + tBURST16", passBurstLength32},
        {tRDWR_dpr, "RD", DependencyType::IntraDIMMRank, "tRDWR_dpr", passBurstLength16},
        {tRDWR_dpr + tBURST16, "RD", DependencyType::IntraDIMMRank, "tRDWR_dpr + tBURST16", passBurstLength32},
        {tRDWR_ddr, "RD", DependencyType::InterDIMMRank, "tRDWR_ddr", passBurstLength16},
        {tRDWR_ddr + tBURST16, "RD", DependencyType::InterDIMMRank, "tRDWR_ddr + tBURST16", passBurstLength32},
        {tCCD_L_RTW_slr, "RDA", DependencyType::IntraBankGroup, "tCCD_L_RTW_slr", passBurstLength16},
        {tCCD_L_RTW_slr + tBURST16, "RDA", DependencyType::IntraBankGroup, "tCCD_L_RTW_slr + tBURST16", passBurstLength32},
        {tCCD_S_RTW_slr, "RDA", DependencyType::IntraLogicalRank, "tCCD_S_RTW_slr", passBurstLength16},
        {tCCD_S_RTW_slr + tBURST16, "RDA", DependencyType::IntraLogicalRank, "tCCD_S_RTW_slr + tBURST16", passBurstLength32},
        {tCCD_RTW_dlr, "RDA", DependencyType::IntraPhysicalRank, "tCCD_RTW_dlr", passBurstLength16},
        {tCCD_RTW_dlr + tBURST16, "RDA", DependencyType::IntraPhysicalRank, "tCCD_RTW_dlr + tBURST16", passBurstLength32},
        {tRDWR_dpr, "RDA", DependencyType::IntraDIMMRank, "tRDWR_dpr", passBurstLength16},
        {tRDWR_dpr + tBURST16, "RDA", DependencyType::IntraDIMMRank, "tRDWR_dpr + tBURST16", passBurstLength32},
        {tRDWR_ddr, "RDA", DependencyType::InterDIMMRank, "tRDWR_ddr", passBurstLength16},
        {tRDWR_ddr + tBURST16, "RDA", DependencyType::InterDIMMRank, "tRDWR_ddr + tBURST16", passBurstLength32},
        {tCCD_L_WR_slr, "WR", DependencyType::IntraBankGroup, "tCCD_L_WR_slr"},
        {tCCD_S_WR_slr, "WR", DependencyType::IntraLogicalRank, "tCCD_S_WR_slr"},
        {tCCD_WR_dlr, "WR", DependencyType::IntraPhysicalRank, "tCCD_WR_dlr", passBurstLength16},
        {tBURST32, "WR", DependencyType::IntraPhysicalRank, "tBURST32", passBurstLength32},
        {tWRWR_dpr, "WR", DependencyType::IntraDIMMRank, "tWRWR_dpr", passBurstLength16},
        {tWRWR_dpr + tBURST16, "WR", DependencyType::IntraDIMMRank, "tWRWR_dpr + tBURST16", passBurstLength32},
        {tWRWR_ddr, "WR", DependencyType::InterDIMMRank, "tWRWR_ddr", passBurstLength16},
        {tWRWR_ddr + tBURST16, "WR", DependencyType::InterDIMMRank, "tWRWR_ddr + tBURST16", passBurstLength32},
        {tCCD_L_WR_slr, "WRA", DependencyType::IntraBankGroup, "tCCD_L_WR_slr", passBurstLength16},
        {tCCD_L_WR_slr + tBURST16, "WRA", DependencyType::IntraBankGroup, "tCCD_L_WR_slr + tBURST16", passBurstLength32},
        {tCCD_S_WR_slr, "WRA", DependencyType::IntraLogicalRank, "tCCD_S_WR_slr"},
        {tCCD_WR_dlr, "WRA", DependencyType::IntraPhysicalRank, "tCCD_WR_dlr", passBurstLength16},
        {tBURST32, "WRA", DependencyType::IntraPhysicalRank, "tBURST32", passBurstLength32},
        {tWRWR_dpr, "WRA", DependencyType::IntraDIMMRank, "tWRWR_dpr", passBurstLength16},
        {tWRWR_dpr + tBURST16, "WRA", DependencyType::IntraDIMMRank, "tWRWR_dpr + tBURST16", passBurstLength32},
        {tWRWR_ddr, "WRA", DependencyType::InterDIMMRank, "tWRWR_ddr", passBurstLength16},
        {tWRWR_ddr + tBURST16, "WRA", DependencyType::InterDIMMRank, "tWRWR_ddr + tBURST16", passBurstLength32},
        {2 * tCK, "CMD_BUS", DependencyType::InterDIMMRank, "CommandBus"},
      }
    )
  );

  dmap.emplace(
    piecewise_construct,
    forward_as_tuple("REFAB"),
    forward_as_tuple(
      initializer_list<TimeDependency>{
        {tRC + cmdLengthDiff, "ACT", DependencyType::IntraLogicalRank, "tRC + tCK"},
        {tRDAACT + cmdLengthDiff, "RDA", DependencyType::IntraPhysicalRank, "tRDAACT + tCK"},
        {tWRPRE + tRP + cmdLengthDiff, "WRA", DependencyType::IntraLogicalRank, "tWRPRE + tRP + tCK", passBurstLength16},
        {tWRPRE + tRP + cmdLengthDiff + tBURST16, "WRA", DependencyType::IntraLogicalRank, "tWRPRE + tRP + tCK + tBURST16", passBurstLength32},
        {tRP, "PREPB", DependencyType::IntraLogicalRank, "tRP"},
        {tRP, "PREAB", DependencyType::IntraLogicalRank, "tRP"},
        {tRFC_slr, "REFAB", DependencyType::IntraLogicalRank, "tRFC_slr"},
        {tRFC_dlr, "REFAB", DependencyType::IntraPhysicalRank, "tRFC_dlr"},
        {tRFC_dpr, "REFAB", DependencyType::IntraDIMMRank, "tRFC_dpr"},
        {tRFC_slr, "RFMAB", DependencyType::IntraLogicalRank, "tRFC_slr"},
        {tRFC_dlr, "RFMAB", DependencyType::IntraPhysicalRank, "tRFC_dlr"},
        {tRFC_dpr, "RFMAB", DependencyType::IntraDIMMRank, "tRFC_dpr"},
        {tCK, "CMD_BUS", DependencyType::InterDIMMRank, "CommandBus"},
      }
    )
  );

  dmap.emplace(
    piecewise_construct,
    forward_as_tuple("RFMAB"),
    forward_as_tuple(
      initializer_list<TimeDependency>{
        {tRC + cmdLengthDiff, "ACT", DependencyType::IntraLogicalRank, "tRC + tCK"},
        {tRDAACT + cmdLengthDiff, "RDA", DependencyType::IntraPhysicalRank, "tRDAACT + tCK"},
        {tWRPRE + tRP + cmdLengthDiff, "WRA", DependencyType::IntraLogicalRank, "tWRPRE + tRP + tCK", passBurstLength16},
        {tWRPRE + tRP + cmdLengthDiff + tBURST16, "WRA", DependencyType::IntraLogicalRank, "tWRPRE + tRP + tCK + tBURST16", passBurstLength32},
        {tRP, "PREPB", DependencyType::IntraLogicalRank, "tRP"},
        {tRP, "PREAB", DependencyType::IntraLogicalRank, "tRP"},
        {tRFC_slr, "REFAB", DependencyType::IntraLogicalRank, "tRFC_slr"},
        {tRFC_dlr, "REFAB", DependencyType::IntraPhysicalRank, "tRFC_dlr"},
        {tRFC_dpr, "REFAB", DependencyType::IntraDIMMRank, "tRFC_dpr"},
        {tRFC_slr, "RFMAB", DependencyType::IntraLogicalRank, "tRFC_slr"},
        {tRFC_dlr, "RFMAB", DependencyType::IntraPhysicalRank, "tRFC_dlr"},
        {tRFC_dpr, "RFMAB", DependencyType::IntraDIMMRank, "tRFC_dpr"},
        {tCK, "CMD_BUS", DependencyType::InterDIMMRank, "CommandBus"},
      }
    )
  );

  dmap.emplace(
    piecewise_construct,
    forward_as_tuple("REFSB"),
    forward_as_tuple(
      initializer_list<TimeDependency>{
        {tRC + cmdLengthDiff, "ACT", DependencyType::IntraBankInGroup, "tRC + tCK"},
        {tRRD_L_slr + cmdLengthDiff, "ACT", DependencyType::IntraLogicalRank, "tRRD_L_slr + tCK"},
        {tRDAACT + cmdLengthDiff, "RDA", DependencyType::IntraBankInGroup, "tRDAACT + tCK"},
        {tWRAACT + tRP + cmdLengthDiff, "WRA", DependencyType::IntraBankInGroup, "tWRAACT + tRP + tCK", passBurstLength16},
        {tWRAACT + tRP + cmdLengthDiff + tBURST16, "WRA", DependencyType::IntraBankInGroup, "tWRAACT + tRP + tCK + tBURST16", passBurstLength32},
        {tRP, "PREPB", DependencyType::IntraBankInGroup, "tRP"},
        {tRP, "PRESB", DependencyType::IntraBankInGroup, "tRP"},
        {tRFC_slr, "REFAB", DependencyType::IntraLogicalRank, "tRFC_slr"},
        {tRFC_dlr, "REFAB", DependencyType::IntraPhysicalRank, "tRFC_dlr"},
        {tRFC_dpr, "REFAB", DependencyType::IntraDIMMRank, "tRFC_dpr"},
        {tRFC_slr, "RFMAB", DependencyType::IntraLogicalRank, "tRFC_slr"},
        {tRFC_dlr, "RFMAB", DependencyType::IntraPhysicalRank, "tRFC_dlr"},
        {tRFC_dpr, "RFMAB", DependencyType::IntraDIMMRank, "tRFC_dpr"},
        {tRFCsb_slr, "REFSB", DependencyType::IntraLogicalRank, "tRFCsb_slr"},
        {tRFCsb_dlr, "REFSB", DependencyType::IntraPhysicalRank, "tRFCsb_dlr"},
        {tRFCsb_slr, "RFMSB", DependencyType::IntraLogicalRank, "tRFCsb_slr"},
        {tRFCsb_dlr, "RFMSB", DependencyType::IntraPhysicalRank, "tRFCsb_dlr"},
        {tCK, "CMD_BUS", DependencyType::InterDIMMRank, "CommandBus"},
        {tFAW_slr - shortCmdOffset, "FAW_LOGICAL", DependencyType::IntraLogicalRank, "tFAW_slr"},
        {tFAW_dlr - shortCmdOffset, "FAW_PHYSICAL", DependencyType::IntraPhysicalRank, "tFAW_dlr"},
      }
    )
  );

  dmap.emplace(
    piecewise_construct,
    forward_as_tuple("RFMSB"),
    forward_as_tuple(
      initializer_list<TimeDependency>{
        {tRC + cmdLengthDiff, "ACT", DependencyType::IntraBankGroup, "tRC + tCK"},
        {tRRD_L_slr + cmdLengthDiff, "ACT", DependencyType::IntraLogicalRank, "tRRD_L_slr + tCK"},
        {tRDAACT + cmdLengthDiff, "RDA", DependencyType::IntraBankGroup, "tRDAACT + tCK"},
        {tWRAACT + tRP + cmdLengthDiff, "WRA", DependencyType::IntraBankGroup, "tWRAACT + tRP + tCK", passBurstLength16},
        {tWRAACT + tRP + cmdLengthDiff + tBURST16, "WRA", DependencyType::IntraBankGroup, "tWRAACT + tRP + tCK + tBURST16", passBurstLength32},
        {tRP, "PREPB", DependencyType::IntraBankGroup, "tRP"},
        {tRP, "PRESB", DependencyType::IntraBankGroup, "tRP"},
        {tRFC_slr, "REFAB", DependencyType::IntraLogicalRank, "tRFC_slr"},
        {tRFC_dlr, "REFAB", DependencyType::IntraPhysicalRank, "tRFC_dlr"},
        {tRFC_dpr, "REFAB", DependencyType::IntraDIMMRank, "tRFC_dpr"},
        {tRFC_slr, "RFMAB", DependencyType::IntraLogicalRank, "tRFC_slr"},
        {tRFC_dlr, "RFMAB", DependencyType::IntraPhysicalRank, "tRFC_dlr"},
        {tRFC_dpr, "RFMAB", DependencyType::IntraDIMMRank, "tRFC_dpr"},
        {tRFCsb_slr, "REFSB", DependencyType::IntraLogicalRank, "tRFCsb_slr"},
        {tRFCsb_dlr, "REFSB", DependencyType::IntraPhysicalRank, "tRFCsb_dlr"},
        {tRFCsb_slr, "RFMSB", DependencyType::IntraLogicalRank, "tRFCsb_slr"},
        {tRFCsb_dlr, "RFMSB", DependencyType::IntraPhysicalRank, "tRFCsb_dlr"},
        {tCK, "CMD_BUS", DependencyType::InterDIMMRank, "CommandBus"},
        {tFAW_slr - shortCmdOffset, "FAW_LOGICAL", DependencyType::IntraLogicalRank, "tFAW_slr"},
        {tFAW_dlr - shortCmdOffset, "FAW_PHYSICAL", DependencyType::IntraPhysicalRank, "tFAW_dlr"},
      }
    )
  );

  dmap.emplace(
    piecewise_construct,
    forward_as_tuple("PREAB"),
    forward_as_tuple(
      initializer_list<TimeDependency>{
        {tRAS + cmdLengthDiff, "ACT", DependencyType::IntraLogicalRank, "tRAS + tCK"},
        {tRTP + cmdLengthDiff, "RD", DependencyType::IntraLogicalRank, "tRTP + tCK"},
        {tRTP + cmdLengthDiff, "RDA", DependencyType::IntraLogicalRank, "tRTP + tCK"},
        {tWRPRE + cmdLengthDiff, "WR", DependencyType::IntraLogicalRank, "tWRPRE + tCK", passBurstLength16},
        {tWRPRE + cmdLengthDiff + tBURST16, "WR", DependencyType::IntraLogicalRank, "tWRPRE + tCK + tBURST16", passBurstLength32},
        {tWRPRE + cmdLengthDiff, "WRA", DependencyType::IntraLogicalRank, "tWRPRE + tCK", passBurstLength16},
        {tWRPRE + cmdLengthDiff + tBURST16, "WRA", DependencyType::IntraLogicalRank, "tWRPRE + tCK + tBURST16", passBurstLength32},
        {tPPD, "PREPB", DependencyType::IntraPhysicalRank, "tPPD"},
        {tPPD, "PREAB", DependencyType::IntraPhysicalRank, "tPPD"},
        {tCK, "CMD_BUS", DependencyType::InterDIMMRank, "CommandBus"},
      }
    )
  );

  dmap.emplace(
    piecewise_construct,
    forward_as_tuple("PRESB"),
    forward_as_tuple(
      initializer_list<TimeDependency>{
        {tRAS + cmdLengthDiff, "ACT", DependencyType::IntraBankInGroup, "tRAS + tCK"},
        {tRTP + cmdLengthDiff, "RD", DependencyType::IntraBankInGroup, "tRTP + tCK"},
        {tRTP + cmdLengthDiff, "RDA", DependencyType::IntraBankInGroup, "tRTP + tCK"},
        {tWRPRE + cmdLengthDiff, "WR", DependencyType::IntraBankInGroup, "tWRPRE + tCK", passBurstLength16},
        {tWRPRE + cmdLengthDiff + tBURST16, "WR", DependencyType::IntraBankInGroup, "tWRPRE + tCK + tBURST16", passBurstLength32},
        {tWRPRE + cmdLengthDiff, "WRA", DependencyType::IntraBankInGroup, "tWRPRE + tCK", passBurstLength16},
        {tWRPRE + cmdLengthDiff + tBURST16, "WRA", DependencyType::IntraBankInGroup, "tWRPRE + tCK + tBURST16", passBurstLength32},
        {tPPD, "PREPB", DependencyType::IntraPhysicalRank, "tPPD"},
        {tPPD, "PREAB", DependencyType::IntraPhysicalRank, "tPPD"},
        {tCK, "CMD_BUS", DependencyType::InterDIMMRank, "CommandBus"},
      }
    )
  );

  return dmap;
}
