// File: /workspace/github_cpp_makefile_star2_O3/NishadSaraf[P]Championship-Simulator/src/drc_controller.cc
// Function: DRC_MEMORY_CONTROLLER::return_data(PACKET*)
void DRC_MEMORY_CONTROLLER::return_data(PACKET *packet)
{
    // check MSHR information
    int mshr_index = check_mshr(packet);

    // sanity check
    if (mshr_index == -1) {
        cerr << "[" << NAME << "_MSHR] " << __func__ << " instr_id: " << packet->instr_id << " cannot find a matching entry!";
        cerr << " full_addr: " << hex << packet->full_addr;
        cerr << " address: " << packet->address << dec;
        cerr << " event: " << packet->event_cycle << " current: " << current_core_cycle[packet->cpu] << endl;
        assert(0);
    }

    // MSHR holds the most updated information about this request
    // no need to do memcpy
    MSHR.num_returned++;
    MSHR.entry[mshr_index].returned = COMPLETED;
    MSHR.entry[mshr_index].data = packet->data;

    // ADD LATENCY
    MSHR.entry[mshr_index].event_cycle = current_core_cycle[packet->cpu];
    packet->event_cycle = current_core_cycle[packet->cpu];
    /*
    if (MSHR.entry[mshr_index].event_cycle < current_core_cycle[packet->cpu])
        MSHR.entry[mshr_index].event_cycle = current_core_cycle[packet->cpu] + LATENCY;
    else
        MSHR.entry[mshr_index].event_cycle += LATENCY;
    */

    // we need to immediately return these data to upper level memory
    // if we don't, it takes a very long time to 
    // 1) change the DRC mode from read to write
    // 2) fill in missing cache blocks in DRC
    // 3) finally return data to upper level cache
    // which eventually stalls the main core pipeline

    // FIXME: need to consider DRC dbus congestion
    // first add it to the wq and make one more function that can return data to on-chip caches

    // check fill level
    if (packet->fill_level < fill_level) {

        if (packet->instruction) 
            upper_level_icache[packet->cpu]->return_data(packet);
        else // data
            upper_level_dcache[packet->cpu]->return_data(packet);

        // since it is now returned to the upper level memory we must reset the fill_level
        // if we don't, when the DRC mode changes to the write mode and this block gets filled in the DRC
        // it will try to retun data again to the upper level memory
        packet->fill_level = FILL_DRC;
    }

    // before we add returned packet to DRC WQ, we must reset scheduled bit in this packet
    // since this packet once scheduled while it was sitting in DRC RQ to be processed
    packet->scheduled = 0;

    // add it to the WQ
    add_wq(packet); 
    update_schedule_cycle(&WQ);

    // even though it is not filled in the DRC yet, we can safely release MSHR resource
    MSHR.remove_queue(&MSHR.entry[mshr_index]);

    DP (if (warmup_complete[packet->cpu]) {
    cout << "[" << NAME << "_MSHR] " <<  __func__ << " instr_id: " << MSHR.entry[mshr_index].instr_id;
    cout << " address: " << hex << MSHR.entry[mshr_index].address << " full_addr: " << MSHR.entry[mshr_index].full_addr;
    cout << " data: " << MSHR.entry[mshr_index].data << dec << " num_returned: " << MSHR.num_returned;
    cout << " index: " << mshr_index << " occupancy: " << MSHR.occupancy;
    cout << " event: " << MSHR.entry[mshr_index].event_cycle << " current: " << current_core_cycle[packet->cpu] << " next: " << MSHR.next_fill_cycle << endl; });
}

// Assembly:
pushq %r15
pushq %r14
pushq %r12
pushq %rbx
pushq %rax
movq %rsi, %rbx
movq %rdi, %r14
movl 0x7368(%rdi), %ecx
testq %rcx, %rcx
je 0x13157
movq 0x407408(%r14), %rax
movq 0x340(%rbx), %rsi
imulq $0x380, %rcx, %rdi      # imm = 0x380
xorl %edx, %edx
movabsq $0x100000000, %r8       # imm = 0x100000000
xorl %ecx, %ecx
cmpq %rsi, 0x340(%rax,%rdx)
je 0x1329d
addq %r8, %rcx
addq $0x380, %rdx            # imm = 0x380
cmpq %rdx, %rdi
jne 0x1313a
movq 0x6e92(%rip), %r15      # 0x19ff0
leaq 0xf2b(%rip), %rsi       # 0x14090
movq %r15, %rdi
callq 0x3250
addq $0x7348, %r14           # imm = 0x7348
movq %rax, %rdi
movq %r14, %rsi
callq 0x31e0
leaq 0x1119(%rip), %rsi      # 0x1429f
movq %rax, %rdi
callq 0x3250
leaq 0x1112(%rip), %rsi      # 0x142a7
movq %rax, %rdi
callq 0x3250
leaq 0x1dac(%rip), %rsi      # 0x14f50
movq %rax, %rdi
callq 0x3250
movq 0x368(%rbx), %rsi
movq %rax, %rdi
callq 0x3090
leaq 0x10f1(%rip), %rsi      # 0x142b3
movq %rax, %rdi
callq 0x3250
leaq 0xfbd(%rip), %rsi       # 0x1418e
movq %r15, %rdi
callq 0x3250
movq (%rax), %rcx
movq -0x18(%rcx), %rcx
movl 0x18(%rax,%rcx), %edx
andl $-0x4b, %edx
orl $0x8, %edx
movl %edx, 0x18(%rax,%rcx)
movq 0x348(%rbx), %rsi
movq %rax, %rdi
callq 0x3090
leaq 0xf7f(%rip), %rsi       # 0x14183
movq %r15, %rdi
callq 0x3250
movq 0x340(%rbx), %rsi
movq %rax, %rdi
callq 0x3090
movq (%rax), %rcx
movq -0x18(%rcx), %rcx
movl 0x18(%rax,%rcx), %edx
andl $-0x4b, %edx
orl $0x2, %edx
movl %edx, 0x18(%rax,%rcx)
leaq 0xf64(%rip), %rsi       # 0x1419b
movq %r15, %rdi
callq 0x3250
movq 0x378(%rbx), %rsi
movq %rax, %rdi
callq 0x3090
leaq 0x107d(%rip), %rsi      # 0x142d2
movq %rax, %rdi
callq 0x3250
movl 0x330(%rbx), %ecx
leaq 0x6dc56(%rip), %rdx     # 0x80ec0
movq (%rdx,%rcx,8), %rsi
movq %rax, %rdi
callq 0x3090
movq %rax, %rdi
callq 0x3110
leaq 0xde2(%rip), %rdi       # 0x14067
leaq 0x1e44(%rip), %rsi      # 0x150d0
leaq 0x1f0b(%rip), %rcx      # 0x1519e
movl $0x381, %edx            # imm = 0x381
callq 0x3160
movabsq $0x37ffffffc80, %rsi    # imm = 0x37FFFFFFC80
cmpq %rsi, %rdx
je 0x13157
incl 0x4073a8(%r14)
sarq $0x20, %rcx
imulq $0x380, %rcx, %r15      # imm = 0x380
movb $0x2, 0x32c(%rax,%r15)
movq 0x360(%rbx), %rcx
movq %rcx, 0x360(%rax,%r15)
movl 0x330(%rbx), %ecx
leaq 0x6dbd9(%rip), %rdx     # 0x80ec0
movq (%rdx,%rcx,8), %rdx
movq %rdx, 0x378(%rax,%r15)
movq %rdx, 0x378(%rbx)
movl 0x8(%rbx), %eax
cmpl 0x40946c(%r14), %eax
jge 0x13327
xorl %eax, %eax
cmpb $0x0, (%rbx)
sete %al
leaq (%r14,%rax,8), %rax
movq 0x8(%rax,%rcx,8), %rdi
movq (%rdi), %rax
movq %rbx, %rsi
callq *0x18(%rax)
movl $0x8, 0x8(%rbx)
leaq 0x407370(%r14), %r12
movb $0x0, 0x2(%rbx)
movq (%r14), %rax
movq %r14, %rdi
movq %rbx, %rsi
callq *0x8(%rax)
leaq 0x40a870(%r14), %rsi
callq 0x11996
addq 0x407408(%r14), %r15
movq %r12, %rdi
movq %r15, %rsi
addq $0x8, %rsp
popq %rbx
popq %r12
popq %r14
popq %r15
jmp 0xc41a
nop