// File: NishadSaraf[P]Championship-Simulator/src/drc_controller.cc
// Function: DRC_MEMORY_CONTROLLER::add_rq(PACKET*)
int DRC_MEMORY_CONTROLLER::add_rq(PACKET *packet)
{
    // check for the latest wirtebacks in the write queue
    //int wq_index = WQ.check_queue(packet);
    int wq_index = check_drc_queue(&WQ, packet);
    if (wq_index != -1) {
        
        // check fill level
        if (packet->fill_level < fill_level) {

            packet->data = WQ.entry[wq_index].data;
            if (packet->instruction) 
                upper_level_icache[packet->cpu]->return_data(packet);
            else // data
                upper_level_dcache[packet->cpu]->return_data(packet);
        }

        DP ( if (packet->cpu) {
        cout << "[" << NAME << "_RQ] " << __func__ << " instr_id: " << packet->instr_id << " found recent writebacks";
        cout << hex << " read: " << packet->address << " writeback: " << WQ.entry[wq_index].address << dec << endl; });

        ACCESS[1]++;
        HIT[1]++;

        WQ.FORWARD++;
        RQ.ACCESS++;
        //assert(0);

        return -1;
    }

    // check for duplicates in the read queue
    int index = check_drc_queue(&RQ, packet);
    if (index != -1)
        return index; // merged index

    // search for the empty index
    for (index=0; index<DRC_RQ_SIZE; index++) {
        if (RQ.entry[index].address == 0) {
            
            memcpy(&RQ.entry[index], packet, sizeof(PACKET));
            RQ.occupancy++;

#ifdef DEBUG_PRINT
            uint32_t channel = drc_get_channel(packet->address),
                     rank = drc_get_rank(packet->address),
                     bank = drc_get_bank(packet->address),
                     row = drc_get_row(packet->address),
                     column = drc_get_column(packet->address); 
#endif

            DP ( if(warmup_complete[packet->cpu]) {
            cout << "[" << NAME << "_RQ] " <<  __func__ << " instr_id: " << packet->instr_id << " address: " << hex << packet->address;
            cout << " full_addr: " << packet->full_addr << dec << " ch: " << channel;
            cout << " rank: " << rank << " bank: " << bank << " row: " << row << " col: " << column;
            cout << " occupancy: " << RQ.occupancy << " current: " << current_core_cycle[packet->cpu] << " event: " << packet->event_cycle << endl; });

            break;
        }
    }

    update_schedule_cycle(&RQ);

    return -1;
}

// Assembly:
subq $0x28, %rsp
movq %rdi, 0x18(%rsp)
movq %rsi, 0x10(%rsp)
movq 0x18(%rsp), %rdi
movq %rdi, (%rsp)
movq %rdi, %rsi
addq $0x40a870, %rsi         # imm = 0x40A870
movq 0x10(%rsp), %rdx
callq 0x21b60
movl %eax, 0xc(%rsp)
cmpl $-0x1, 0xc(%rsp)
je 0x21a80
movq (%rsp), %rcx
movq 0x10(%rsp), %rax
movl 0x8(%rax), %eax
cmpl 0x40946c(%rcx), %eax
jge 0x21a27
movq (%rsp), %rax
movq 0x40a908(%rax), %rax
movslq 0xc(%rsp), %rcx
imulq $0x380, %rcx, %rcx      # imm = 0x380
addq %rcx, %rax
movq 0x360(%rax), %rcx
movq 0x10(%rsp), %rax
movq %rcx, 0x360(%rax)
movq 0x10(%rsp), %rax
cmpb $0x0, (%rax)
je 0x21a06
movq (%rsp), %rax
movq 0x10(%rsp), %rcx
movl 0x330(%rcx), %ecx
movq 0x8(%rax,%rcx,8), %rdi
movq 0x10(%rsp), %rsi
movq (%rdi), %rax
callq *0x18(%rax)
jmp 0x21a25
movq (%rsp), %rax
movq 0x10(%rsp), %rcx
movl 0x330(%rcx), %ecx
movq 0x10(%rax,%rcx,8), %rdi
movq 0x10(%rsp), %rsi
movq (%rdi), %rax
callq *0x18(%rax)
jmp 0x21a27
movq (%rsp), %rax
movq 0x72b0(%rax), %rcx
addq $0x1, %rcx
movq %rcx, 0x72b0(%rax)
movq 0x72d0(%rax), %rcx
addq $0x1, %rcx
movq %rcx, 0x72d0(%rax)
movq 0x40a8d8(%rax), %rcx
addq $0x1, %rcx
movq %rcx, 0x40a8d8(%rax)
movq 0x40c570(%rax), %rcx
addq $0x1, %rcx
movq %rcx, 0x40c570(%rax)
movl $0xffffffff, 0x24(%rsp) # imm = 0xFFFFFFFF
jmp 0x21b4b
movq (%rsp), %rdi
movq %rdi, %rsi
addq $0x40c510, %rsi         # imm = 0x40C510
movq 0x10(%rsp), %rdx
callq 0x21b60
movl %eax, 0x8(%rsp)
cmpl $-0x1, 0x8(%rsp)
je 0x21ab0
movl 0x8(%rsp), %eax
movl %eax, 0x24(%rsp)
jmp 0x21b4b
movl $0x0, 0x8(%rsp)
cmpl $0x30, 0x8(%rsp)
jge 0x21b30
movq (%rsp), %rax
movq 0x40c5a8(%rax), %rax
movslq 0x8(%rsp), %rcx
imulq $0x380, %rcx, %rcx      # imm = 0x380
addq %rcx, %rax
cmpq $0x0, 0x340(%rax)
jne 0x21b21
movq (%rsp), %rax
movq 0x40c5a8(%rax), %rdi
movslq 0x8(%rsp), %rax
imulq $0x380, %rax, %rax      # imm = 0x380
addq %rax, %rdi
movq 0x10(%rsp), %rsi
movl $0x380, %edx            # imm = 0x380
callq 0x31a0
movq (%rsp), %rax
movl 0x40c544(%rax), %ecx
addl $0x1, %ecx
movl %ecx, 0x40c544(%rax)
jmp 0x21b30
jmp 0x21b23
movl 0x8(%rsp), %eax
addl $0x1, %eax
movl %eax, 0x8(%rsp)
jmp 0x21ab8
movq (%rsp), %rdi
movq %rdi, %rsi
addq $0x40c510, %rsi         # imm = 0x40C510
callq 0x1e6f0
movl $0xffffffff, 0x24(%rsp) # imm = 0xFFFFFFFF
movl 0x24(%rsp), %eax
addq $0x28, %rsp
retq
nopw %cs:(%rax,%rax)