// File: CMU-SAFARI[P]ramulator/src/DSARP.cpp
// Function: ramulator::DSARP::init_prereq()
void DSARP::init_prereq()
{
  // RD
  prereq[int(Level::Rank)][int(Command::RD)] = [] (DRAM<DSARP>* node, Command cmd, int id) {
    switch (int(node->state)) {
      case int(State::PowerUp): return Command::MAX;
      case int(State::ActPowerDown): return Command::PDX;
      case int(State::PrePowerDown): return Command::PDX;
      case int(State::SelfRefresh): return Command::SRX;
      default: assert(false);
    }};
  // Rank transitions to Bank
  prereq[int(Level::Bank)][int(Command::RD)] = [] (DRAM<DSARP>* node, Command cmd, int id) {
    switch (int(node->state)) {
      case int(State::Closed): return Command::ACT;
      case int(State::Opened):
        // Really is the subarray state. If the subarray matches, check the row ID
        if (node->row_state.find(id) != node->row_state.end())
          return Command::MAX;
        return Command::PRE;
      default: assert(false);
    }};
  // Bank transitions to Subarray
  prereq[int(Level::SubArray)][int(Command::RD)] = [] (DRAM<DSARP>* node, Command cmd, int id) {
    switch (int(node->state)) {
      case int(State::Closed): return Command::ACT;
      case int(State::Opened):
        // Actual row state
        if (node->row_state.find(id) != node->row_state.end())
          return cmd;
        return Command::PRE;
      default: assert(false);
    }};

  // WR
  prereq[int(Level::Rank)][int(Command::WR)] = prereq[int(Level::Rank)][int(Command::RD)];
  prereq[int(Level::Bank)][int(Command::WR)] = prereq[int(Level::Bank)][int(Command::RD)];
  prereq[int(Level::SubArray)][int(Command::WR)] = prereq[int(Level::SubArray)][int(Command::RD)];

  // REF -- on all banks
  prereq[int(Level::Rank)][int(Command::REF)] = [] (DRAM<DSARP>* node, Command cmd, int id) {
    for (auto bank : node->children) {
      if (bank->state == State::Closed)
        continue;
      return Command::PREA;
    }
    return Command::REF;};

  // REF -- per bank
  prereq[int(Level::Bank)][int(Command::REFPB)] = [] (DRAM<DSARP>* node, Command cmd, int id) {
    if (node->state == State::Closed) return Command::REFPB;
    else return Command::PRE;};

  // PD
  prereq[int(Level::Rank)][int(Command::PDE)] = [] (DRAM<DSARP>* node, Command cmd, int id) {
    switch (int(node->state)) {
      case int(State::PowerUp): return Command::PDE;
      case int(State::ActPowerDown): return Command::PDE;
      case int(State::PrePowerDown): return Command::PDE;
      case int(State::SelfRefresh): return Command::SRX;
      default: assert(false);
    }};

  // SR
  prereq[int(Level::Rank)][int(Command::SRE)] = [] (DRAM<DSARP>* node, Command cmd, int id) {
    switch (int(node->state)) {
      case int(State::PowerUp): return Command::SRE;
      case int(State::ActPowerDown): return Command::PDX;
      case int(State::PrePowerDown): return Command::PDX;
      case int(State::SelfRefresh): return Command::SRE;
      default: assert(false);
    }};
}

// Assembly:
pushq %rbp
movq %rsp, %rbp
subq $0x20, %rsp
movq %rdi, -0x8(%rbp)
movq -0x8(%rbp), %rdi
movq %rdi, -0x18(%rbp)
addq $0x210, %rdi            # imm = 0x210
addq $0x1a0, %rdi            # imm = 0x1A0
addq $0x60, %rdi
leaq -0x9(%rbp), %rsi
callq 0x1a8a60
movq -0x18(%rbp), %rdi
addq $0x210, %rdi            # imm = 0x210
addq $0x340, %rdi            # imm = 0x340
addq $0x60, %rdi
leaq -0xa(%rbp), %rsi
callq 0x1a8ab0
movq -0x18(%rbp), %rdi
addq $0x210, %rdi            # imm = 0x210
addq $0x4e0, %rdi            # imm = 0x4E0
addq $0x60, %rdi
leaq -0xb(%rbp), %rsi
callq 0x1a8b00
movq -0x18(%rbp), %rdi
movq %rdi, %rsi
addq $0x210, %rsi            # imm = 0x210
addq $0x1a0, %rsi            # imm = 0x1A0
addq $0x60, %rsi
addq $0x210, %rdi            # imm = 0x210
addq $0x1a0, %rdi            # imm = 0x1A0
addq $0x80, %rdi
callq 0x1b05a0
movq -0x18(%rbp), %rdi
movq %rdi, %rsi
addq $0x210, %rsi            # imm = 0x210
addq $0x340, %rsi            # imm = 0x340
addq $0x60, %rsi
addq $0x210, %rdi            # imm = 0x210
addq $0x340, %rdi            # imm = 0x340
addq $0x80, %rdi
callq 0x1b05a0
movq -0x18(%rbp), %rdi
movq %rdi, %rsi
addq $0x210, %rsi            # imm = 0x210
addq $0x4e0, %rsi            # imm = 0x4E0
addq $0x60, %rsi
addq $0x210, %rdi            # imm = 0x210
addq $0x4e0, %rdi            # imm = 0x4E0
addq $0x80, %rdi
callq 0x1b05a0
movq -0x18(%rbp), %rdi
addq $0x210, %rdi            # imm = 0x210
addq $0x1a0, %rdi            # imm = 0x1A0
addq $0xe0, %rdi
leaq -0xc(%rbp), %rsi
callq 0x1a8b50
movq -0x18(%rbp), %rdi
addq $0x210, %rdi            # imm = 0x210
addq $0x340, %rdi            # imm = 0x340
addq $0x100, %rdi            # imm = 0x100
leaq -0xd(%rbp), %rsi
callq 0x1a8ba0
movq -0x18(%rbp), %rdi
addq $0x210, %rdi            # imm = 0x210
addq $0x1a0, %rdi            # imm = 0x1A0
addq $0x120, %rdi            # imm = 0x120
leaq -0xe(%rbp), %rsi
callq 0x1a8bf0
movq -0x18(%rbp), %rdi
addq $0x210, %rdi            # imm = 0x210
addq $0x1a0, %rdi            # imm = 0x1A0
addq $0x160, %rdi            # imm = 0x160
leaq -0xf(%rbp), %rsi
callq 0x1a8c40
addq $0x20, %rsp
popq %rbp
retq
nopw %cs:(%rax,%rax)