// File: NishadSaraf[P]Championship-Simulator/src/drc_controller.cc
// Function: DRC_MEMORY_CONTROLLER::operate()
void DRC_MEMORY_CONTROLLER::operate()
{
    if (do_write == 0) {
        if (WQ.occupancy >= DRC_WRITE_HIGH_WM) {
            do_write = 1;
            processed_writes = 0;
            last_drc_read_mode = current_core_cycle[0];
            //cout << "DRC is now WRITE mode cycle: " << current_core_cycle[0] << endl;

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

            for (uint32_t i=0; i<DRC_CHANNELS; i++) {
                // add data bus turnaround time
                dbus_cycle_available[i] += DRC_DBUS_TURN_AROUND_TIME;
            }
        }
    } else {
        if (WQ.occupancy == 0)
            do_write = 0;
        else if (RQ.occupancy && (WQ.occupancy < DRC_WRITE_LOW_WM))
            do_write = 0;
        else if (RQ.occupancy && (MIN_DRC_WRITES_PER_SWITCH <= processed_writes))
            do_write = 0;

        if (do_write == 0) {
            processed_writes = 0;
            last_drc_write_mode = current_core_cycle[0];
            //cout << "DRC is now READ  mode cycle: " << current_core_cycle[0] << endl;

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

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

    // do FR-FCFS scheduling

    // handle write
    // schedule new entry
    //for (uint32_t channel=0; channel<DRC_CHANNELS; channel++) {
        //if (write_mode[channel] && (WQ.next_schedule_index < WQ.SIZE)) {
        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);
                //schedule(channel, &WQ);
        }
    //}

    // process DRC requests
    //for (uint32_t channel=0; channel<DRC_CHANNELS; channel++) {
        //if (write_mode[channel] && (WQ.next_process_index < WQ.SIZE)) {
        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(channel, &WQ);
                process(&WQ);
        }
    //}

    // handle read
    // schedule new entry
    //for (uint32_t channel=0; channel<DRC_CHANNELS; channel++) {
        //if ((write_mode[channel] == 0) && (RQ.next_schedule_index < RQ.SIZE)) {
        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);
                //schedule(channel, &RQ);
        }
    //}

    // process DRC requests
    //for (uint32_t channel=0; channel<DRC_CHANNELS; channel++) {
        //if ((write_mode[channel] == 0) && (RQ.next_process_index < RQ.SIZE)) {
        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);
                //process(channel, &RQ);
        }
    //}
}

// Assembly:
subq $0x18, %rsp
movq %rdi, 0x10(%rsp)
movq 0x10(%rsp), %rax
movq %rax, (%rsp)
movzbl 0x40944c(%rax), %eax
cmpl $0x0, %eax
jne 0x1e9a3
movq (%rsp), %rax
cmpl $0x24, 0x40a8a4(%rax)
jb 0x1e99e
movq (%rsp), %rdi
movb $0x1, 0x40944c(%rdi)
movl $0x0, 0x409450(%rdi)
leaq 0x71575(%rip), %rax     # 0x8fec0
movq (%rax), %rax
movq %rax, 0x8d4d3(%rip)     # 0xabe28
movq %rdi, %rsi
addq $0x40c510, %rsi         # imm = 0x40C510
callq 0x1e170
movl $0x0, 0xc(%rsp)
cmpl $0x4, 0xc(%rsp)
jae 0x1e99c
movq (%rsp), %rax
movl 0xc(%rsp), %ecx
movq 0x409010(%rax,%rcx,8), %rdx
addq $0x18, %rdx
movq %rdx, 0x409010(%rax,%rcx,8)
movl 0xc(%rsp), %eax
addl $0x1, %eax
movl %eax, 0xc(%rsp)
jmp 0x1e96c
jmp 0x1e99e
jmp 0x1ea8b
movq (%rsp), %rax
cmpl $0x0, 0x40a8a4(%rax)
jne 0x1e9bd
movq (%rsp), %rax
movb $0x0, 0x40944c(%rax)
jmp 0x1ea11
movq (%rsp), %rax
cmpl $0x0, 0x40c544(%rax)
je 0x1e9e4
movq (%rsp), %rax
cmpl $0xc, 0x40a8a4(%rax)
jae 0x1e9e4
movq (%rsp), %rax
movb $0x0, 0x40944c(%rax)
jmp 0x1ea0f
movq (%rsp), %rax
cmpl $0x0, 0x40c544(%rax)
je 0x1ea0d
movq (%rsp), %rcx
movl $0xc, %eax
cmpl 0x409450(%rcx), %eax
ja 0x1ea0d
movq (%rsp), %rax
movb $0x0, 0x40944c(%rax)
jmp 0x1ea0f
jmp 0x1ea11
movq (%rsp), %rax
movzbl 0x40944c(%rax), %eax
cmpl $0x0, %eax
jne 0x1ea89
movq (%rsp), %rdi
movl $0x0, 0x409450(%rdi)
leaq 0x7148a(%rip), %rax     # 0x8fec0
movq (%rax), %rax
movq %rax, 0x8d3f0(%rip)     # 0xabe30
movq %rdi, %rsi
addq $0x40a870, %rsi         # imm = 0x40A870
callq 0x1e170
movl $0x0, 0x8(%rsp)
cmpl $0x4, 0x8(%rsp)
jae 0x1ea87
movq (%rsp), %rax
movl 0x8(%rsp), %ecx
movq 0x409010(%rax,%rcx,8), %rdx
addq $0x18, %rdx
movq %rdx, 0x409010(%rax,%rcx,8)
movl 0x8(%rsp), %eax
addl $0x1, %eax
movl %eax, 0x8(%rsp)
jmp 0x1ea57
jmp 0x1ea89
jmp 0x1ea8b
movq (%rsp), %rax
cmpb $0x0, 0x40944c(%rax)
je 0x1eaf6
movq (%rsp), %rcx
movl 0x40a8b0(%rcx), %eax
cmpl 0x40a890(%rcx), %eax
jae 0x1eaf6
movq (%rsp), %rdx
movq 0x40a8c0(%rdx), %rax
movq 0x40a908(%rdx), %rcx
movl 0x40a8b0(%rdx), %edx
imulq $0x380, %rdx, %rdx      # imm = 0x380
addq %rdx, %rcx
movl 0x330(%rcx), %ecx
movl %ecx, %edx
leaq 0x713e5(%rip), %rcx     # 0x8fec0
cmpq (%rcx,%rdx,8), %rax
ja 0x1eaf4
movq (%rsp), %rdi
movq %rdi, %rsi
addq $0x40a870, %rsi         # imm = 0x40A870
callq 0x1ec50
jmp 0x1eaf6
movq (%rsp), %rax
cmpb $0x0, 0x40944c(%rax)
je 0x1eb61
movq (%rsp), %rcx
movl 0x40a8b4(%rcx), %eax
cmpl 0x40a890(%rcx), %eax
jae 0x1eb61
movq (%rsp), %rdx
movq 0x40a8c8(%rdx), %rax
movq 0x40a908(%rdx), %rcx
movl 0x40a8b4(%rdx), %edx
imulq $0x380, %rdx, %rdx      # imm = 0x380
addq %rdx, %rcx
movl 0x330(%rcx), %ecx
movl %ecx, %edx
leaq 0x7137a(%rip), %rcx     # 0x8fec0
cmpq (%rcx,%rdx,8), %rax
ja 0x1eb5f
movq (%rsp), %rdi
movq %rdi, %rsi
addq $0x40a870, %rsi         # imm = 0x40A870
callq 0x1f330
jmp 0x1eb61
movq (%rsp), %rax
movzbl 0x40944c(%rax), %eax
cmpl $0x0, %eax
jne 0x1ebcf
movq (%rsp), %rcx
movl 0x40c550(%rcx), %eax
cmpl 0x40c530(%rcx), %eax
jae 0x1ebcf
movq (%rsp), %rdx
movq 0x40c560(%rdx), %rax
movq 0x40c5a8(%rdx), %rcx
movl 0x40c550(%rdx), %edx
imulq $0x380, %rdx, %rdx      # imm = 0x380
addq %rdx, %rcx
movl 0x330(%rcx), %ecx
movl %ecx, %edx
leaq 0x7130c(%rip), %rcx     # 0x8fec0
cmpq (%rcx,%rdx,8), %rax
ja 0x1ebcd
movq (%rsp), %rdi
movq %rdi, %rsi
addq $0x40c510, %rsi         # imm = 0x40C510
callq 0x1ec50
jmp 0x1ebcf
movq (%rsp), %rax
movzbl 0x40944c(%rax), %eax
cmpl $0x0, %eax
jne 0x1ec3d
movq (%rsp), %rcx
movl 0x40c554(%rcx), %eax
cmpl 0x40c530(%rcx), %eax
jae 0x1ec3d
movq (%rsp), %rdx
movq 0x40c568(%rdx), %rax
movq 0x40c5a8(%rdx), %rcx
movl 0x40c554(%rdx), %edx
imulq $0x380, %rdx, %rdx      # imm = 0x380
addq %rdx, %rcx
movl 0x330(%rcx), %ecx
movl %ecx, %edx
leaq 0x7129e(%rip), %rcx     # 0x8fec0
cmpq (%rcx,%rdx,8), %rax
ja 0x1ec3b
movq (%rsp), %rdi
movq %rdi, %rsi
addq $0x40c510, %rsi         # imm = 0x40C510
callq 0x1f330
jmp 0x1ec3d
addq $0x18, %rsp
retq
nopw %cs:(%rax,%rax)