// File: CMU-SAFARI[P]ramulator/src/Controller.h
// Function: ramulator::Controller<ramulator::DDR3>::cmd_issue_autoprecharge(ramulator::DDR3::Command&, std::vector<int, std::allocator<int>> const&)
void cmd_issue_autoprecharge(typename T::Command& cmd,
                                            const vector<int>& addr_vec) {

        // currently, autoprecharge is only used with closed row policy
        if(channel->spec->is_accessing(cmd) && rowpolicy->type == RowPolicy<T>::Type::ClosedAP) {
            // check if it is the last request to the opened row
            Queue* queue = write_mode ? &writeq : &readq;

            auto begin = addr_vec.begin();
            vector<int> rowgroup(begin, begin + int(T::Level::Row) + 1);

			int num_row_hits = 0;

            for (auto itr = queue->q.begin(); itr != queue->q.end(); ++itr) {
                if (is_row_hit(itr)) { 
                    auto begin2 = itr->addr_vec.begin();
                    vector<int> rowgroup2(begin2, begin2 + int(T::Level::Row) + 1);
                    if(rowgroup == rowgroup2)
                        num_row_hits++;
                }
            }

            if(num_row_hits == 0) {
                Queue* queue = &actq;
                for (auto itr = queue->q.begin(); itr != queue->q.end(); ++itr) {
                    if (is_row_hit(itr)) {
                        auto begin2 = itr->addr_vec.begin();
                        vector<int> rowgroup2(begin2, begin2 + int(T::Level::Row) + 1);
                        if(rowgroup == rowgroup2)
                            num_row_hits++;
                    }
                }
            }

            assert(num_row_hits > 0); // The current request should be a hit, 
                                      // so there should be at least one request 
                                      // that hits in the current open row
            if(num_row_hits == 1) {
                if(cmd == T::Command::RD)
                    cmd = T::Command::RDA;
                else if (cmd == T::Command::WR)
                    cmd = T::Command::WRA;
                else
                    assert(false && "Unimplemented command type.");
            }
        }

    }

// Assembly:
pushq %rbp
movq %rsp, %rbp
subq $0x170, %rsp            # imm = 0x170
movq %rdi, -0x8(%rbp)
movq %rsi, -0x10(%rbp)
movq %rdx, -0x18(%rbp)
movq -0x8(%rbp), %rax
movq %rax, -0x130(%rbp)
movq 0x1098(%rax), %rax
movq 0x390(%rax), %rdi
movq -0x10(%rbp), %rax
movl (%rax), %esi
callq 0x44f10
testb $0x1, %al
jne 0x44514
jmp 0x449e6
movq -0x130(%rbp), %rax
movq 0x10a8(%rax), %rax
cmpl $0x1, 0x8(%rax)
jne 0x449e6
movq -0x130(%rbp), %rax
testb $0x1, 0x1190(%rax)
je 0x44552
movq -0x130(%rbp), %rax
addq $0x10e0, %rax           # imm = 0x10E0
movq %rax, -0x138(%rbp)
jmp 0x44566
movq -0x130(%rbp), %rax
addq $0x10c0, %rax           # imm = 0x10C0
movq %rax, -0x138(%rbp)
movq -0x138(%rbp), %rax
movq %rax, -0x20(%rbp)
movq -0x18(%rbp), %rdi
callq 0x2fac0
movq %rax, -0x28(%rbp)
movq -0x28(%rbp), %rax
movq %rax, -0x48(%rbp)
leaq -0x28(%rbp), %rdi
movl $0x3, %esi
callq 0x2faf0
movq %rax, -0x58(%rbp)
leaq -0x58(%rbp), %rdi
movl $0x1, %esi
callq 0x2faf0
movq %rax, -0x50(%rbp)
leaq -0x59(%rbp), %rdi
movq %rdi, -0x140(%rbp)
callq 0x2fb30
movq -0x140(%rbp), %rcx
movq -0x48(%rbp), %rsi
movq -0x50(%rbp), %rdx
leaq -0x40(%rbp), %rdi
callq 0x2fb50
jmp 0x445d4
leaq -0x59(%rbp), %rdi
callq 0x2fbd0
movl $0x0, -0x70(%rbp)
movq -0x20(%rbp), %rdi
callq 0x42b70
movq %rax, -0x78(%rbp)
movq -0x20(%rbp), %rdi
callq 0x417c0
movq %rax, -0x80(%rbp)
leaq -0x78(%rbp), %rdi
leaq -0x80(%rbp), %rsi
callq 0x41790
testb $0x1, %al
jne 0x44614
jmp 0x44795
movq -0x130(%rbp), %rdi
movq -0x78(%rbp), %rax
movq %rax, -0x88(%rbp)
movq -0x88(%rbp), %rsi
callq 0x311e0
movb %al, -0x141(%rbp)
jmp 0x4463a
movb -0x141(%rbp), %al
testb $0x1, %al
jne 0x44649
jmp 0x44785
leaq -0x78(%rbp), %rdi
callq 0x2eb90
movq %rax, %rdi
addq $0x10, %rdi
callq 0x334e0
movq %rax, -0x90(%rbp)
movq -0x90(%rbp), %rax
movq %rax, -0xb0(%rbp)
leaq -0x90(%rbp), %rdi
movl $0x3, %esi
callq 0x43350
movq %rax, -0xc0(%rbp)
leaq -0xc0(%rbp), %rdi
movl $0x1, %esi
callq 0x43350
movq %rax, -0xb8(%rbp)
leaq -0xc1(%rbp), %rdi
movq %rdi, -0x150(%rbp)
callq 0x2fb30
movq -0x150(%rbp), %rcx
movq -0xb0(%rbp), %rsi
movq -0xb8(%rbp), %rdx
leaq -0xa8(%rbp), %rdi
callq 0x43390
jmp 0x446d9
leaq -0xc1(%rbp), %rdi
callq 0x2fbd0
leaq -0x40(%rbp), %rdi
leaq -0xa8(%rbp), %rsi
callq 0x43540
movb %al, -0x151(%rbp)
jmp 0x446fd
movb -0x151(%rbp), %al
testb $0x1, %al
jne 0x44709
jmp 0x44779
movl -0x70(%rbp), %eax
addl $0x1, %eax
movl %eax, -0x70(%rbp)
jmp 0x44779
movq %rax, %rcx
movl %edx, %eax
movq %rcx, -0x68(%rbp)
movl %eax, -0x6c(%rbp)
leaq -0x59(%rbp), %rdi
callq 0x2fbd0
jmp 0x449ef
movq %rax, %rcx
movl %edx, %eax
movq %rcx, -0x68(%rbp)
movl %eax, -0x6c(%rbp)
jmp 0x449db
movq %rax, %rcx
movl %edx, %eax
movq %rcx, -0x68(%rbp)
movl %eax, -0x6c(%rbp)
leaq -0xc1(%rbp), %rdi
callq 0x2fbd0
jmp 0x449db
movq %rax, %rcx
movl %edx, %eax
movq %rcx, -0x68(%rbp)
movl %eax, -0x6c(%rbp)
leaq -0xa8(%rbp), %rdi
callq 0x2fcd0
jmp 0x449db
leaq -0xa8(%rbp), %rdi
callq 0x2fcd0
jmp 0x44787
leaq -0x78(%rbp), %rdi
callq 0x42f20
jmp 0x445f1
cmpl $0x0, -0x70(%rbp)
jne 0x44956
movq -0x130(%rbp), %rax
addq $0x1100, %rax           # imm = 0x1100
movq %rax, -0xd0(%rbp)
movq -0xd0(%rbp), %rdi
callq 0x42b70
movq %rax, -0xd8(%rbp)
movq -0xd0(%rbp), %rdi
callq 0x417c0
movq %rax, -0xe0(%rbp)
leaq -0xd8(%rbp), %rdi
leaq -0xe0(%rbp), %rsi
callq 0x41790
testb $0x1, %al
jne 0x447f5
jmp 0x44954
movq -0x130(%rbp), %rdi
movq -0xd8(%rbp), %rax
movq %rax, -0xe8(%rbp)
movq -0xe8(%rbp), %rsi
callq 0x311e0
movb %al, -0x152(%rbp)
jmp 0x4481e
movb -0x152(%rbp), %al
testb $0x1, %al
jne 0x4482d
jmp 0x44941
leaq -0xd8(%rbp), %rdi
callq 0x2eb90
movq %rax, %rdi
addq $0x10, %rdi
callq 0x334e0
movq %rax, -0xf0(%rbp)
movq -0xf0(%rbp), %rax
movq %rax, -0x110(%rbp)
leaq -0xf0(%rbp), %rdi
movl $0x3, %esi
callq 0x43350
movq %rax, -0x120(%rbp)
leaq -0x120(%rbp), %rdi
movl $0x1, %esi
callq 0x43350
movq %rax, -0x118(%rbp)
leaq -0x121(%rbp), %rdi
movq %rdi, -0x160(%rbp)
callq 0x2fb30
movq -0x160(%rbp), %rcx
movq -0x110(%rbp), %rsi
movq -0x118(%rbp), %rdx
leaq -0x108(%rbp), %rdi
callq 0x43390
jmp 0x448c0
leaq -0x121(%rbp), %rdi
callq 0x2fbd0
leaq -0x40(%rbp), %rdi
leaq -0x108(%rbp), %rsi
callq 0x43540
movb %al, -0x161(%rbp)
jmp 0x448e4
movb -0x161(%rbp), %al
testb $0x1, %al
jne 0x448f0
jmp 0x44935
movl -0x70(%rbp), %eax
addl $0x1, %eax
movl %eax, -0x70(%rbp)
jmp 0x44935
movq %rax, %rcx
movl %edx, %eax
movq %rcx, -0x68(%rbp)
movl %eax, -0x6c(%rbp)
leaq -0x121(%rbp), %rdi
callq 0x2fbd0
jmp 0x449db
movq %rax, %rcx
movl %edx, %eax
movq %rcx, -0x68(%rbp)
movl %eax, -0x6c(%rbp)
leaq -0x108(%rbp), %rdi
callq 0x2fcd0
jmp 0x449db
leaq -0x108(%rbp), %rdi
callq 0x2fcd0
jmp 0x44943
leaq -0xd8(%rbp), %rdi
callq 0x42f20
jmp 0x447c6
jmp 0x44956
cmpl $0x0, -0x70(%rbp)
jle 0x4495e
jmp 0x4497d
leaq 0x20c99b(%rip), %rdi    # 0x251300
leaq 0x20c8f7(%rip), %rsi    # 0x251263
movl $0x247, %edx            # imm = 0x247
leaq 0x20c999(%rip), %rcx    # 0x251311
callq 0xc280
cmpl $0x1, -0x70(%rbp)
jne 0x449d0
movq -0x10(%rbp), %rax
cmpl $0x3, (%rax)
jne 0x44998
movq -0x10(%rbp), %rax
movl $0x5, (%rax)
jmp 0x449ce
movq -0x10(%rbp), %rax
cmpl $0x4, (%rax)
jne 0x449ad
movq -0x10(%rbp), %rax
movl $0x6, (%rax)
jmp 0x449cc
leaq 0x20c9e4(%rip), %rdi    # 0x251398
leaq 0x20c8a8(%rip), %rsi    # 0x251263
movl $0x250, %edx            # imm = 0x250
leaq 0x20c94a(%rip), %rcx    # 0x251311
callq 0xc280
jmp 0x449ce
jmp 0x449d0
leaq -0x40(%rbp), %rdi
callq 0x2fcd0
jmp 0x449e6
leaq -0x40(%rbp), %rdi
callq 0x2fcd0
jmp 0x449ef
addq $0x170, %rsp            # imm = 0x170
popq %rbp
retq
movq -0x68(%rbp), %rdi
callq 0xc5d0
nopl (%rax,%rax)