// File: /workspace/github_cpp_makefile_star2_O3/NishadSaraf[P]Championship-Simulator/src/dram_controller.cc
// Function: MEMORY_CONTROLLER::add_rq(PACKET*)
int MEMORY_CONTROLLER::add_rq(PACKET *packet)
{
    // simply return read requests with dummy response before the warmup
    if (all_warmup_complete < NUM_CPUS) {
        if (packet->instruction) 
            upper_level_icache[packet->cpu]->return_data(packet);
        else // data
            upper_level_dcache[packet->cpu]->return_data(packet);

        return -1;
    }

    // check for the latest wirtebacks in the write queue
    //int wq_index = WQ.check_queue(packet);
    int wq_index = check_dram_queue(&WQ, packet);
    if (wq_index != -1) {
        
        // no need to 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 = RQ.check_queue(packet);
    int index = check_dram_queue(&RQ, packet);
    if (index != -1)
        return index; // merged index

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

#ifdef DEBUG_PRINT
            uint32_t channel = dram_get_channel(packet->address),
                     rank = dram_get_rank(packet->address),
                     bank = dram_get_bank(packet->address),
                     row = dram_get_row(packet->address),
                     column = dram_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:
pushq %r14
pushq %rbx
pushq %rax
movq %rdi, %rbx
leaq 0xe3a5(%rip), %rax      # 0x1a343
cmpb $0x0, (%rax)
je 0xbfea
movl 0x8278(%rbx), %ecx
testq %rcx, %rcx
je 0xc016
movl $0xffffffff, %edx       # imm = 0xFFFFFFFF
movq 0x82f0(%rbx), %rax
movq 0x340(%rsi), %r8
imulq $0x380, %rcx, %r9       # imm = 0x380
xorl %edi, %edi
xorl %ecx, %ecx
cmpq %r8, 0x340(%rax,%rdi)
je 0xc003
addq %rdx, %rcx
incq %rcx
addq $0x380, %rdi            # imm = 0x380
cmpq %rdi, %r9
jne 0xbfcc
jmp 0xc016
cmpb $0x0, (%rsi)
movl 0x330(%rsi), %eax
je 0xc0a2
movq 0x8(%rbx,%rax,8), %rdi
jmp 0xc0a7
movabsq $0x37ffffffc80, %rdx    # imm = 0x37FFFFFFC80
cmpq %rdx, %rdi
jne 0xc0af
movl 0x9f18(%rbx), %ecx
testq %rcx, %rcx
je 0xc05a
movq 0x340(%rsi), %rdx
movl $0x340, %edi            # imm = 0x340
addq 0x9f90(%rbx), %rdi
xorl %eax, %eax
cmpq %rdx, (%rdi)
je 0xc04c
incq %rax
addq $0x380, %rdi            # imm = 0x380
cmpq %rax, %rcx
jne 0xc036
jmp 0xc05a
movl $0xffffffff, %ecx       # imm = 0xFFFFFFFF
cmpq %rcx, %rax
jne 0xc107
leaq 0x9ef8(%rbx), %r14
movq 0x9f90(%rbx), %rdi
xorl %eax, %eax
cmpq $0x0, 0x340(%rdi,%rax)
je 0xc085
addq $0x380, %rax            # imm = 0x380
cmpq $0xa800, %rax           # imm = 0xA800
jne 0xc06a
jmp 0xc098
addq %rax, %rdi
movl $0x380, %edx            # imm = 0x380
callq 0x31c0
incl 0x9f2c(%rbx)
movq %r14, %rsi
callq 0xb848
jmp 0xc102
movq 0x10(%rbx,%rax,8), %rdi
movq (%rdi), %rax
callq *0x18(%rax)
jmp 0xc102
sarq $0x20, %rcx
imulq $0x380, %rcx, %rcx      # imm = 0x380
movq 0x360(%rax,%rcx), %rax
movq %rax, 0x360(%rsi)
xorl %eax, %eax
cmpb $0x0, (%rsi)
sete %al
movl 0x330(%rsi), %ecx
leaq (%rbx,%rax,8), %rax
movq 0x8(%rax,%rcx,8), %rdi
movq (%rdi), %rax
callq *0x18(%rax)
incq 0x72b0(%rbx)
incq 0x72d0(%rbx)
incq 0x82c0(%rbx)
incq 0x9f58(%rbx)
movl $0xffffffff, %eax       # imm = 0xFFFFFFFF
addq $0x8, %rsp
popq %rbx
popq %r14
retq
nop