// File: CMU-SAFARI[P]SMLA/src/Scheduler.h
// Function: ramulator::Scheduler<ramulator::WideIO>::get_head(std::__cxx11::list<ramulator::Request, std::allocator<ramulator::Request>>&)
list<Request>::iterator get_head(list<Request>& q)
    {
      // TODO make the decision at compile time
      if (type != Type::FRFCFS_PriorHit) {
        if (!q.size())
            return q.end();

        auto head = q.begin();
        for (auto itr = next(q.begin(), 1); itr != q.end(); itr++)
            head = compare[int(type)](head, itr);

        return head;
      } else {
        if (!q.size())
            return q.end();

        auto head = q.begin();
        for (auto itr = next(q.begin(), 1); itr != q.end(); itr++) {
            head = compare[int(Type::FRFCFS_PriorHit)](head, itr);
        }

        if (this->ctrl->is_ready(head) && this->ctrl->is_row_hit(head)) {
          return head;
        }

        // prepare a list of hit request
        vector<vector<int>> hit_reqs;
        for (auto itr = q.begin() ; itr != q.end() ; ++itr) {
          if (this->ctrl->is_row_hit(itr)) {
            auto begin = itr->addr_vec.begin();
            // TODO Here it assumes all DRAM standards use PRE to close a row
            // It's better to make it more general.
            auto end = begin + int(ctrl->channel->spec->scope[int(T::Command::PRE)]) + 1;
            vector<int> rowgroup(begin, end); // bank or subarray
            hit_reqs.push_back(rowgroup);
          }
        }
        // if we can't find proper request, we need to return q.end(),
        // so that no command will be scheduled
        head = q.end();
        for (auto itr = q.begin(); itr != q.end(); itr++) {
          bool violate_hit = false;
          if ((!this->ctrl->is_row_hit(itr)) && this->ctrl->is_row_open(itr)) {
            // so the next instruction to be scheduled is PRE, might violate hit
            auto begin = itr->addr_vec.begin();
            // TODO Here it assumes all DRAM standards use PRE to close a row
            // It's better to make it more general.
            auto end = begin + int(ctrl->channel->spec->scope[int(T::Command::PRE)]) + 1;
            vector<int> rowgroup(begin, end); // bank or subarray
            for (const auto& hit_req_rowgroup : hit_reqs) {
              if (rowgroup == hit_req_rowgroup) {
                  violate_hit = true;
                  break;
              }
            }
          }
          if (violate_hit) {
            continue;
          }
          // If it comes here, that means it won't violate any hit request
          if (head == q.end()) {
            head = itr;
          } else {
            head = compare[int(Type::FRFCFS)](head, itr);
          }
        }

        return head;
      }
    }

// Assembly:
pushq %rbp
movq %rsp, %rbp
subq $0x220, %rsp            # imm = 0x220
movq %rdi, -0x10(%rbp)
movq %rsi, -0x18(%rbp)
movq -0x10(%rbp), %rax
movq %rax, -0x1e8(%rbp)
cmpl $0x3, 0x8(%rax)
je 0x2a3ed
movq -0x18(%rbp), %rdi
callq 0x29ca0
cmpq $0x0, %rax
jne 0x2a349
movq -0x18(%rbp), %rdi
callq 0x2aa90
movq %rax, -0x8(%rbp)
jmp 0x2aa42
movq -0x18(%rbp), %rdi
callq 0x2bdf0
movq %rax, -0x8(%rbp)
movq -0x18(%rbp), %rdi
callq 0x2bdf0
movq %rax, -0x28(%rbp)
movq -0x28(%rbp), %rdi
movl $0x1, %esi
callq 0x2c810
movq %rax, -0x20(%rbp)
movq -0x18(%rbp), %rdi
callq 0x2aa90
movq %rax, -0x30(%rbp)
leaq -0x20(%rbp), %rdi
leaq -0x30(%rbp), %rsi
callq 0x2bcc0
testb $0x1, %al
jne 0x2a395
jmp 0x2a3e8
movq -0x1e8(%rbp), %rax
movq %rax, %rdi
addq $0x18, %rdi
movslq 0x8(%rax), %rax
shlq $0x5, %rax
addq %rax, %rdi
movq -0x8(%rbp), %rax
movq %rax, -0x40(%rbp)
movq -0x20(%rbp), %rax
movq %rax, -0x48(%rbp)
movq -0x40(%rbp), %rsi
movq -0x48(%rbp), %rdx
callq 0x2c840
movq %rax, -0x38(%rbp)
movq -0x38(%rbp), %rax
movq %rax, -0x8(%rbp)
leaq -0x20(%rbp), %rdi
xorl %esi, %esi
callq 0x2c890
movq %rax, -0x50(%rbp)
jmp 0x2a375
jmp 0x2aa42
movq -0x18(%rbp), %rdi
callq 0x29ca0
cmpq $0x0, %rax
jne 0x2a40e
movq -0x18(%rbp), %rdi
callq 0x2aa90
movq %rax, -0x8(%rbp)
jmp 0x2aa42
movq -0x18(%rbp), %rdi
callq 0x2bdf0
movq %rax, -0x8(%rbp)
movq -0x18(%rbp), %rdi
callq 0x2bdf0
movq %rax, -0x60(%rbp)
movq -0x60(%rbp), %rdi
movl $0x1, %esi
callq 0x2c810
movq %rax, -0x58(%rbp)
movq -0x18(%rbp), %rdi
callq 0x2aa90
movq %rax, -0x68(%rbp)
leaq -0x58(%rbp), %rdi
leaq -0x68(%rbp), %rsi
callq 0x2bcc0
testb $0x1, %al
jne 0x2a45a
jmp 0x2a4a6
movq -0x1e8(%rbp), %rdi
addq $0x18, %rdi
addq $0x60, %rdi
movq -0x8(%rbp), %rax
movq %rax, -0x78(%rbp)
movq -0x58(%rbp), %rax
movq %rax, -0x80(%rbp)
movq -0x78(%rbp), %rsi
movq -0x80(%rbp), %rdx
callq 0x2c840
movq %rax, -0x70(%rbp)
movq -0x70(%rbp), %rax
movq %rax, -0x8(%rbp)
leaq -0x58(%rbp), %rdi
xorl %esi, %esi
callq 0x2c890
movq %rax, -0x88(%rbp)
jmp 0x2a43a
movq -0x1e8(%rbp), %rax
movq (%rax), %rdi
movq -0x8(%rbp), %rax
movq %rax, -0x90(%rbp)
movq -0x90(%rbp), %rsi
callq 0x1bf80
testb $0x1, %al
jne 0x2a4cd
jmp 0x2a4f9
movq -0x1e8(%rbp), %rax
movq (%rax), %rdi
movq -0x8(%rbp), %rax
movq %rax, -0x98(%rbp)
movq -0x98(%rbp), %rsi
callq 0x1f530
testb $0x1, %al
jne 0x2a4f4
jmp 0x2a4f9
jmp 0x2aa42
leaq -0xb0(%rbp), %rdi
callq 0x208c0
movq -0x18(%rbp), %rdi
callq 0x2bdf0
movq %rax, -0xb8(%rbp)
movq -0x18(%rbp), %rdi
callq 0x2aa90
movq %rax, -0xc0(%rbp)
leaq -0xb8(%rbp), %rdi
leaq -0xc0(%rbp), %rsi
callq 0x2bcc0
testb $0x1, %al
jne 0x2a541
jmp 0x2a6d9
movq -0x1e8(%rbp), %rax
movq (%rax), %rdi
movq -0xb8(%rbp), %rax
movq %rax, -0xc8(%rbp)
movq -0xc8(%rbp), %rsi
callq 0x1f530
movb %al, -0x1e9(%rbp)
jmp 0x2a56d
movb -0x1e9(%rbp), %al
testb $0x1, %al
jne 0x2a57c
jmp 0x2a6c6
leaq -0xb8(%rbp), %rdi
callq 0x1ba90
movq %rax, %rdi
addq $0x10, %rdi
callq 0x1c9e0
movq %rax, %rcx
movq -0x1e8(%rbp), %rax
movq %rcx, -0xe0(%rbp)
movq (%rax), %rax
movq 0x1000(%rax), %rax
movq 0x390(%rax), %rax
movslq 0x184(%rax), %rsi
leaq -0xe0(%rbp), %rdi
callq 0x1ca10
movq %rax, -0xf0(%rbp)
leaq -0xf0(%rbp), %rdi
movl $0x1, %esi
callq 0x1ca10
movq %rax, -0xe8(%rbp)
movq -0xe0(%rbp), %rax
movq %rax, -0x110(%rbp)
movq -0xe8(%rbp), %rax
movq %rax, -0x118(%rbp)
leaq -0x119(%rbp), %rdi
movq %rdi, -0x1f8(%rbp)
callq 0x1ca50
movq -0x1f8(%rbp), %rcx
movq -0x110(%rbp), %rsi
movq -0x118(%rbp), %rdx
leaq -0x108(%rbp), %rdi
callq 0x1ca70
jmp 0x2a63a
leaq -0x119(%rbp), %rdi
callq 0x1caf0
leaq -0xb0(%rbp), %rdi
leaq -0x108(%rbp), %rsi
callq 0x2c8c0
jmp 0x2a65b
leaq -0x108(%rbp), %rdi
callq 0x1cca0
jmp 0x2a6c6
movq %rax, %rcx
movl %edx, %eax
movq %rcx, -0xd0(%rbp)
movl %eax, -0xd4(%rbp)
jmp 0x2aa34
movq %rax, %rcx
movl %edx, %eax
movq %rcx, -0xd0(%rbp)
movl %eax, -0xd4(%rbp)
leaq -0x119(%rbp), %rdi
callq 0x1caf0
jmp 0x2aa34
movq %rax, %rcx
movl %edx, %eax
movq %rcx, -0xd0(%rbp)
movl %eax, -0xd4(%rbp)
leaq -0x108(%rbp), %rdi
callq 0x1cca0
jmp 0x2aa34
jmp 0x2a6c8
leaq -0xb8(%rbp), %rdi
callq 0x2c490
jmp 0x2a515
movq -0x18(%rbp), %rdi
callq 0x2aa90
movq %rax, -0x128(%rbp)
movq -0x128(%rbp), %rax
movq %rax, -0x8(%rbp)
movq -0x18(%rbp), %rdi
callq 0x2bdf0
movq %rax, -0x130(%rbp)
movq -0x18(%rbp), %rdi
callq 0x2aa90
movq %rax, -0x138(%rbp)
leaq -0x130(%rbp), %rdi
leaq -0x138(%rbp), %rsi
callq 0x2bcc0
testb $0x1, %al
jne 0x2a730
jmp 0x2aa26
movq -0x1e8(%rbp), %rax
movb $0x0, -0x139(%rbp)
movq (%rax), %rdi
movq -0x130(%rbp), %rax
movq %rax, -0x148(%rbp)
movq -0x148(%rbp), %rsi
callq 0x1f530
movb %al, -0x1f9(%rbp)
jmp 0x2a763
movb -0x1f9(%rbp), %al
testb $0x1, %al
jne 0x2a970
jmp 0x2a773
movq -0x1e8(%rbp), %rax
movq (%rax), %rdi
movq -0x130(%rbp), %rax
movq %rax, -0x150(%rbp)
movq -0x150(%rbp), %rsi
callq 0x2ae30
movb %al, -0x1fa(%rbp)
jmp 0x2a79f
movb -0x1fa(%rbp), %al
testb $0x1, %al
jne 0x2a7ae
jmp 0x2a970
leaq -0x130(%rbp), %rdi
callq 0x1ba90
movq %rax, %rdi
addq $0x10, %rdi
callq 0x1c9e0
movq %rax, %rcx
movq -0x1e8(%rbp), %rax
movq %rcx, -0x158(%rbp)
movq (%rax), %rax
movq 0x1000(%rax), %rax
movq 0x390(%rax), %rax
movslq 0x184(%rax), %rsi
leaq -0x158(%rbp), %rdi
callq 0x1ca10
movq %rax, -0x168(%rbp)
leaq -0x168(%rbp), %rdi
movl $0x1, %esi
callq 0x1ca10
movq %rax, -0x160(%rbp)
movq -0x158(%rbp), %rax
movq %rax, -0x188(%rbp)
movq -0x160(%rbp), %rax
movq %rax, -0x190(%rbp)
leaq -0x191(%rbp), %rdi
movq %rdi, -0x208(%rbp)
callq 0x1ca50
movq -0x208(%rbp), %rcx
movq -0x188(%rbp), %rsi
movq -0x190(%rbp), %rdx
leaq -0x180(%rbp), %rdi
callq 0x1ca70
jmp 0x2a86c
leaq -0x191(%rbp), %rdi
callq 0x1caf0
leaq -0xb0(%rbp), %rax
movq %rax, -0x1a0(%rbp)
movq -0x1a0(%rbp), %rdi
callq 0x2c930
movq %rax, -0x1a8(%rbp)
movq -0x1a0(%rbp), %rdi
callq 0x2c960
movq %rax, -0x1b0(%rbp)
leaq -0x1a8(%rbp), %rdi
leaq -0x1b0(%rbp), %rsi
callq 0x2c990
testb $0x1, %al
jne 0x2a8c8
jmp 0x2a964
leaq -0x1a8(%rbp), %rdi
callq 0x2c9d0
movq %rax, -0x1b8(%rbp)
movq -0x1b8(%rbp), %rsi
leaq -0x180(%rbp), %rdi
callq 0x2c9f0
movb %al, -0x209(%rbp)
jmp 0x2a8f6
movb -0x209(%rbp), %al
testb $0x1, %al
jne 0x2a902
jmp 0x2a951
movb $0x1, -0x139(%rbp)
jmp 0x2a964
movq %rax, %rcx
movl %edx, %eax
movq %rcx, -0xd0(%rbp)
movl %eax, -0xd4(%rbp)
leaq -0x191(%rbp), %rdi
callq 0x1caf0
jmp 0x2aa34
movq %rax, %rcx
movl %edx, %eax
movq %rcx, -0xd0(%rbp)
movl %eax, -0xd4(%rbp)
leaq -0x180(%rbp), %rdi
callq 0x1cca0
jmp 0x2aa34
jmp 0x2a953
leaq -0x1a8(%rbp), %rdi
callq 0x2ca70
jmp 0x2a8ac
leaq -0x180(%rbp), %rdi
callq 0x1cca0
testb $0x1, -0x139(%rbp)
je 0x2a97e
jmp 0x2aa0c
movq -0x18(%rbp), %rdi
callq 0x2aa90
movq %rax, -0x1c0(%rbp)
leaq -0x8(%rbp), %rdi
leaq -0x1c0(%rbp), %rsi
callq 0x2aa60
testb $0x1, %al
jne 0x2a9a4
jmp 0x2a9b1
movq -0x130(%rbp), %rax
movq %rax, -0x8(%rbp)
jmp 0x2aa0a
movq -0x1e8(%rbp), %rdi
addq $0x38, %rdi
movq -0x8(%rbp), %rax
movq %rax, -0x1d0(%rbp)
movq -0x130(%rbp), %rax
movq %rax, -0x1d8(%rbp)
movq -0x1d0(%rbp), %rsi
movq -0x1d8(%rbp), %rdx
callq 0x2c840
movq %rax, -0x218(%rbp)
jmp 0x2a9f1
movq -0x218(%rbp), %rax
movq %rax, -0x1c8(%rbp)
movq -0x1c8(%rbp), %rax
movq %rax, -0x8(%rbp)
jmp 0x2aa0c
leaq -0x130(%rbp), %rdi
xorl %esi, %esi
callq 0x2c890
movq %rax, -0x1e0(%rbp)
jmp 0x2a704
leaq -0xb0(%rbp), %rdi
callq 0x209c0
jmp 0x2aa42
leaq -0xb0(%rbp), %rdi
callq 0x209c0
jmp 0x2aa4f
movq -0x8(%rbp), %rax
addq $0x220, %rsp            # imm = 0x220
popq %rbp
retq
movq -0xd0(%rbp), %rdi
callq 0x65b0
nopl (%rax,%rax)