// File: NishadSaraf[P]Championship-Simulator/src/dram_controller.cc
// Function: MEMORY_CONTROLLER::operate()
void MEMORY_CONTROLLER::operate()
{
    if (do_write == 0) {
        if (WQ.occupancy >= DRAM_WRITE_HIGH_WM) {
            do_write = 1;
            processed_writes = 0;

            // reset scheduled RQ requests
            reset_remain_requests(&RQ);

            for (uint32_t i=0; i<DRAM_CHANNELS; i++) {
                // add data bus turnaround time
                dbus_cycle_available[i] += DRAM_DBUS_TURN_AROUND_TIME;
            }
        }
    }
    else {
        if (WQ.occupancy == 0)
            do_write = 0;
        else if (RQ.occupancy && (WQ.occupancy < DRAM_WRITE_LOW_WM))
            do_write = 0;
        else if (RQ.occupancy && (MIN_DRAM_WRITES_PER_SWITCH <= processed_writes))
            do_write = 0;

        if (do_write == 0) {
            processed_writes = 0;

            // reset scheduled WQ requests
            reset_remain_requests(&WQ);

            for (uint32_t i=0; i<DRAM_CHANNELS; i++) {
                // add data bus turnaround time
                dbus_cycle_available[i] += DRAM_DBUS_TURN_AROUND_TIME;
            }
        }
    }

    // do FR-FCFS scheduling

    // handle write
    // schedule new entry
    if (do_write && (WQ.next_schedule_index < WQ.SIZE)) {
        if (WQ.next_schedule_cycle <= current_core_cycle[WQ.entry[WQ.next_schedule_index].cpu])
            schedule(&WQ);
    }

    // process DRAM requests
    if (do_write && (WQ.next_process_index < WQ.SIZE)) {
        if (WQ.next_process_cycle <= current_core_cycle[WQ.entry[WQ.next_process_index].cpu])
            process(&WQ);
    }

    // handle read
    // schedule new entry
    if ((do_write == 0) && (RQ.next_schedule_index < RQ.SIZE)) {
        if (RQ.next_schedule_cycle <= current_core_cycle[RQ.entry[RQ.next_schedule_index].cpu])
            schedule(&RQ);
    }

    // process DRAM requests
    if ((do_write == 0) && (RQ.next_process_index < RQ.SIZE)) {
        if (RQ.next_process_cycle <= current_core_cycle[RQ.entry[RQ.next_process_index].cpu])
            process(&RQ);
    }
}

// Assembly:
subq $0x18, %rsp
movq %rdi, 0x10(%rsp)
movq 0x10(%rsp), %rax
movq %rax, (%rsp)
movzbl 0x7840(%rax), %eax
cmpl $0x0, %eax
jne 0x137ce
movq (%rsp), %rax
cmpl $0x24, 0x828c(%rax)
jb 0x137c9
movq (%rsp), %rdi
movb $0x1, 0x7840(%rdi)
movl $0x0, 0x7844(%rdi)
movq %rdi, %rsi
addq $0x9ef8, %rsi           # imm = 0x9EF8
callq 0x12fd0
movl $0x0, 0xc(%rsp)
cmpl $0x1, 0xc(%rsp)
jae 0x137c7
movq (%rsp), %rax
movl 0xc(%rsp), %ecx
movq 0x7568(%rax,%rcx,8), %rdx
addq $0x18, %rdx
movq %rdx, 0x7568(%rax,%rcx,8)
movl 0xc(%rsp), %eax
addl $0x1, %eax
movl %eax, 0xc(%rsp)
jmp 0x13797
jmp 0x137c9
jmp 0x138a5
movq (%rsp), %rax
cmpl $0x0, 0x828c(%rax)
jne 0x137e8
movq (%rsp), %rax
movb $0x0, 0x7840(%rax)
jmp 0x1383c
movq (%rsp), %rax
cmpl $0x0, 0x9f2c(%rax)
je 0x1380f
movq (%rsp), %rax
cmpl $0xc, 0x828c(%rax)
jae 0x1380f
movq (%rsp), %rax
movb $0x0, 0x7840(%rax)
jmp 0x1383a
movq (%rsp), %rax
cmpl $0x0, 0x9f2c(%rax)
je 0x13838
movq (%rsp), %rcx
movl $0xc, %eax
cmpl 0x7844(%rcx), %eax
ja 0x13838
movq (%rsp), %rax
movb $0x0, 0x7840(%rax)
jmp 0x1383a
jmp 0x1383c
movq (%rsp), %rax
movzbl 0x7840(%rax), %eax
cmpl $0x0, %eax
jne 0x138a3
movq (%rsp), %rdi
movl $0x0, 0x7844(%rdi)
movq %rdi, %rsi
addq $0x8258, %rsi           # imm = 0x8258
callq 0x12fd0
movl $0x0, 0x8(%rsp)
cmpl $0x1, 0x8(%rsp)
jae 0x138a1
movq (%rsp), %rax
movl 0x8(%rsp), %ecx
movq 0x7568(%rax,%rcx,8), %rdx
addq $0x18, %rdx
movq %rdx, 0x7568(%rax,%rcx,8)
movl 0x8(%rsp), %eax
addl $0x1, %eax
movl %eax, 0x8(%rsp)
jmp 0x13871
jmp 0x138a3
jmp 0x138a5
movq (%rsp), %rax
cmpb $0x0, 0x7840(%rax)
je 0x13910
movq (%rsp), %rcx
movl 0x8298(%rcx), %eax
cmpl 0x8278(%rcx), %eax
jae 0x13910
movq (%rsp), %rdx
movq 0x82a8(%rdx), %rax
movq 0x82f0(%rdx), %rcx
movl 0x8298(%rdx), %edx
imulq $0x380, %rdx, %rdx      # imm = 0x380
addq %rdx, %rcx
movl 0x330(%rcx), %ecx
movl %ecx, %edx
leaq 0x7c5cb(%rip), %rcx     # 0x8fec0
cmpq (%rcx,%rdx,8), %rax
ja 0x1390e
movq (%rsp), %rdi
movq %rdi, %rsi
addq $0x8258, %rsi           # imm = 0x8258
callq 0x13a60
jmp 0x13910
movq (%rsp), %rax
cmpb $0x0, 0x7840(%rax)
je 0x1397b
movq (%rsp), %rcx
movl 0x829c(%rcx), %eax
cmpl 0x8278(%rcx), %eax
jae 0x1397b
movq (%rsp), %rdx
movq 0x82b0(%rdx), %rax
movq 0x82f0(%rdx), %rcx
movl 0x829c(%rdx), %edx
imulq $0x380, %rdx, %rdx      # imm = 0x380
addq %rdx, %rcx
movl 0x330(%rcx), %ecx
movl %ecx, %edx
leaq 0x7c560(%rip), %rcx     # 0x8fec0
cmpq (%rcx,%rdx,8), %rax
ja 0x13979
movq (%rsp), %rdi
movq %rdi, %rsi
addq $0x8258, %rsi           # imm = 0x8258
callq 0x14180
jmp 0x1397b
movq (%rsp), %rax
movzbl 0x7840(%rax), %eax
cmpl $0x0, %eax
jne 0x139e9
movq (%rsp), %rcx
movl 0x9f38(%rcx), %eax
cmpl 0x9f18(%rcx), %eax
jae 0x139e9
movq (%rsp), %rdx
movq 0x9f48(%rdx), %rax
movq 0x9f90(%rdx), %rcx
movl 0x9f38(%rdx), %edx
imulq $0x380, %rdx, %rdx      # imm = 0x380
addq %rdx, %rcx
movl 0x330(%rcx), %ecx
movl %ecx, %edx
leaq 0x7c4f2(%rip), %rcx     # 0x8fec0
cmpq (%rcx,%rdx,8), %rax
ja 0x139e7
movq (%rsp), %rdi
movq %rdi, %rsi
addq $0x9ef8, %rsi           # imm = 0x9EF8
callq 0x13a60
jmp 0x139e9
movq (%rsp), %rax
movzbl 0x7840(%rax), %eax
cmpl $0x0, %eax
jne 0x13a57
movq (%rsp), %rcx
movl 0x9f3c(%rcx), %eax
cmpl 0x9f18(%rcx), %eax
jae 0x13a57
movq (%rsp), %rdx
movq 0x9f50(%rdx), %rax
movq 0x9f90(%rdx), %rcx
movl 0x9f3c(%rdx), %edx
imulq $0x380, %rdx, %rdx      # imm = 0x380
addq %rdx, %rcx
movl 0x330(%rcx), %ecx
movl %ecx, %edx
leaq 0x7c484(%rip), %rcx     # 0x8fec0
cmpq (%rcx,%rdx,8), %rax
ja 0x13a55
movq (%rsp), %rdi
movq %rdi, %rsi
addq $0x9ef8, %rsi           # imm = 0x9EF8
callq 0x14180
jmp 0x13a57
addq $0x18, %rsp
retq
nopl (%rax)