// File: /workspace/github_cpp_makefile_star2_O1/NishadSaraf[P]Championship-Simulator/src/cache.cc
// Function: CACHE::handle_fill()
void CACHE::handle_fill()
{
    // handle fill
    uint32_t fill_cpu = (MSHR.next_fill_index == MSHR_SIZE) ? NUM_CPUS : MSHR.entry[MSHR.next_fill_index].cpu;
    if (fill_cpu == NUM_CPUS)
        return;

    if (MSHR.next_fill_cycle <= current_core_cycle[fill_cpu]) {

#ifdef SANITY_CHECK
        if (MSHR.next_fill_index >= MSHR.SIZE)
            assert(0);
#endif

        uint32_t mshr_index = MSHR.next_fill_index;

        // find victim
        uint32_t set = get_set(MSHR.entry[mshr_index].address), way;
        if (cache_type == IS_LLC) {
            way = llc_find_victim(fill_cpu, MSHR.entry[mshr_index].instr_id, set, block[set], MSHR.entry[mshr_index].ip, MSHR.entry[mshr_index].full_addr, MSHR.entry[mshr_index].type);
        }
        else
            way = find_victim(fill_cpu, MSHR.entry[mshr_index].instr_id, set, block[set], MSHR.entry[mshr_index].ip, MSHR.entry[mshr_index].full_addr, MSHR.entry[mshr_index].type);

#ifdef LLC_BYPASS
        if ((cache_type == IS_LLC) && (way == LLC_WAY)) { // this is a bypass that does not fill the LLC

            // update replacement policy
            if (cache_type == IS_LLC) {
                llc_update_replacement_state(fill_cpu, set, way, MSHR.entry[mshr_index].full_addr, MSHR.entry[mshr_index].ip, 0, MSHR.entry[mshr_index].type, 0);

            }
            else
                update_replacement_state(fill_cpu, set, way, MSHR.entry[mshr_index].full_addr, MSHR.entry[mshr_index].ip, 0, MSHR.entry[mshr_index].type, 0);

            // COLLECT STATS
            sim_miss[fill_cpu][MSHR.entry[mshr_index].type]++;
            sim_access[fill_cpu][MSHR.entry[mshr_index].type]++;

            // check fill level
            if (MSHR.entry[mshr_index].fill_level < fill_level) {

                if (MSHR.entry[mshr_index].instruction) 
                    upper_level_icache[fill_cpu]->return_data(&MSHR.entry[mshr_index]);
                else // data
                    upper_level_dcache[fill_cpu]->return_data(&MSHR.entry[mshr_index]);
            }

            MSHR.remove_queue(&MSHR.entry[mshr_index]);
            MSHR.num_returned--;

            update_fill_cycle();

            return; // return here, no need to process further in this function
        }
#endif

        uint8_t  do_fill = 1;

        // is this dirty?
        if (block[set][way].dirty) {

            // check if the lower level WQ has enough room to keep this writeback request
            if (lower_level) {
                if (lower_level->get_occupancy(2) == lower_level->get_size(2)) {

                    // lower level WQ is full, cannot replace this victim
                    do_fill = 0;
                    lower_level->increment_WQ_FULL();
                    STALL[MSHR.entry[mshr_index].type]++;

                    DP ( if (warmup_complete[fill_cpu]) {
                    cout << "[" << NAME << "] " << __func__ << "do_fill: " << +do_fill;
                    cout << " lower level wq is full!" << " fill_addr: " << hex << MSHR.entry[mshr_index].address;
                    cout << " victim_addr: " << block[set][way].tag << dec << endl; });
                }
                else {
                    PACKET writeback_packet;

                    writeback_packet.fill_level = fill_level << 1;
                    writeback_packet.cpu = fill_cpu;
                    writeback_packet.address = block[set][way].address;
                    writeback_packet.full_addr = block[set][way].full_addr;
                    writeback_packet.data = block[set][way].data;
                    writeback_packet.instr_id = MSHR.entry[mshr_index].instr_id;
                    writeback_packet.ip = 0; // writeback does not have ip
                    writeback_packet.type = WRITEBACK;
                    writeback_packet.event_cycle = current_core_cycle[fill_cpu];

                    lower_level->add_wq(&writeback_packet);
                }
            }
#ifdef SANITY_CHECK
            else {
                // sanity check
                if (cache_type != IS_STLB)
                    assert(0);
            }
#endif
        }

        if (do_fill) {
            // update prefetcher
            if (cache_type == IS_L1D)
                l1d_prefetcher_cache_fill(MSHR.entry[mshr_index].full_addr, set, way, (MSHR.entry[mshr_index].type == PREFETCH) ? 1 : 0, block[set][way].full_addr);
            if  (cache_type == IS_L2C)
                l2c_prefetcher_cache_fill(MSHR.entry[mshr_index].full_addr, set, way, (MSHR.entry[mshr_index].type == PREFETCH) ? 1 : 0, block[set][way].full_addr);

            // update replacement policy
            if (cache_type == IS_LLC) {
                llc_update_replacement_state(fill_cpu, set, way, MSHR.entry[mshr_index].full_addr, MSHR.entry[mshr_index].ip, block[set][way].full_addr, MSHR.entry[mshr_index].type, 0);

            }
            else
                update_replacement_state(fill_cpu, set, way, MSHR.entry[mshr_index].full_addr, MSHR.entry[mshr_index].ip, block[set][way].full_addr, MSHR.entry[mshr_index].type, 0);

            // COLLECT STATS
            sim_miss[fill_cpu][MSHR.entry[mshr_index].type]++;
            sim_access[fill_cpu][MSHR.entry[mshr_index].type]++;

            fill_cache(set, way, &MSHR.entry[mshr_index]);

            // RFO marks cache line dirty
            if (cache_type == IS_L1D) {
                if (MSHR.entry[mshr_index].type == RFO)
                    block[set][way].dirty = 1;
            }

            // check fill level
            if (MSHR.entry[mshr_index].fill_level < fill_level) {

                if (MSHR.entry[mshr_index].instruction) 
                    upper_level_icache[fill_cpu]->return_data(&MSHR.entry[mshr_index]);
                else // data
                    upper_level_dcache[fill_cpu]->return_data(&MSHR.entry[mshr_index]);
            }

            // update processed packets
            if (cache_type == IS_ITLB) { 
                MSHR.entry[mshr_index].instruction_pa = block[set][way].data;
                if (PROCESSED.occupancy < PROCESSED.SIZE)
                    PROCESSED.add_queue(&MSHR.entry[mshr_index]);
            }
            else if (cache_type == IS_DTLB) {
                MSHR.entry[mshr_index].data_pa = block[set][way].data;
                if (PROCESSED.occupancy < PROCESSED.SIZE)
                    PROCESSED.add_queue(&MSHR.entry[mshr_index]);
            }
            else if (cache_type == IS_L1I) {
                if (PROCESSED.occupancy < PROCESSED.SIZE)
                    PROCESSED.add_queue(&MSHR.entry[mshr_index]);
            }
            //else if (cache_type == IS_L1D) {
            else if ((cache_type == IS_L1D) && (MSHR.entry[mshr_index].type != PREFETCH)) {
                if (PROCESSED.occupancy < PROCESSED.SIZE)
                    PROCESSED.add_queue(&MSHR.entry[mshr_index]);
            }

            MSHR.remove_queue(&MSHR.entry[mshr_index]);
            MSHR.num_returned--;

            update_fill_cycle();
        }
    }
}

// Assembly:
pushq %rbp
pushq %r15
pushq %r14
pushq %r13
pushq %r12
pushq %rbx
subq $0x3a8, %rsp            # imm = 0x3A8
movq %rdi, %rbx
movl 0xc9c4(%rdi), %eax
movl $0x1, %ebp
cmpl 0x7388(%rdi), %eax
je 0x3968
movq 0xca20(%rbx), %rcx
imulq $0x380, %rax, %rdx      # imm = 0x380
movl 0x330(%rcx,%rdx), %ebp
cmpl $0x1, %ebp
je 0x3f93
movq 0xc9d0(%rbx), %rcx
movl %ebp, %edx
leaq 0x7d53f(%rip), %rsi     # 0x80ec0
cmpq (%rsi,%rdx,8), %rcx
ja 0x3f93
cmpl 0xc9a8(%rbx), %eax
jae 0x3fa5
movq %rdx, 0x18(%rsp)
movq 0xca20(%rbx), %rcx
imulq $0x380, %rax, %r14      # imm = 0x380
movl 0x340(%rcx,%r14), %r15d
movl 0x7370(%rbx), %edi
callq 0x9196
movl $0xffffffff, %r12d      # imm = 0xFFFFFFFF
movl %eax, %ecx
shll %cl, %r12d
notl %r12d
andl %r15d, %r12d
cmpb $0x6, 0x73a4(%rbx)
movq 0xca20(%rbx), %rcx
movq 0x348(%rcx,%r14), %rax
movq 0x368(%rcx,%r14), %rdx
movq 0x7390(%rbx), %rsi
movq (%rsi,%r12,8), %r8
movq 0x370(%rcx,%r14), %r9
movzbl 0x32f(%rcx,%r14), %r10d
movq %rbx, %rdi
movl %ebp, %esi
movl %r12d, %ecx
jne 0x3a1c
pushq %r10
pushq %rax
callq 0x13856
jmp 0x3a24
pushq %r10
pushq %rax
callq 0x136b8
addq $0x10, %rsp
movl %eax, %r13d
leaq 0xc988(%rbx), %r15
movb 0x73a4(%rbx), %al
cmpb $0x6, %al
setne %cl
cmpl $0x10, %r13d
setne %dl
orb %cl, %dl
je 0x3ad9
movq 0x7390(%rbx), %rcx
movl %r12d, %edx
movq %rdx, 0x10(%rsp)
movq (%rcx,%rdx,8), %rcx
movl %r13d, %edx
leaq (%rdx,%rdx,4), %rdx
shlq $0x4, %rdx
movq %rdx, 0x8(%rsp)
cmpb $0x0, 0x2(%rcx,%rdx)
je 0x3cd1
movq 0x18(%rbx), %rdi
testq %rdi, %rdi
je 0x3b9f
movq %r15, 0x20(%rsp)
movq (%rdi), %rax
movl $0x2, %esi
callq *0x30(%rax)
movl %eax, %r15d
movq 0x18(%rbx), %rdi
movq (%rdi), %rax
movl $0x2, %esi
callq *0x38(%rax)
cmpl %eax, %r15d
jne 0x3bc6
movq 0x18(%rbx), %rdi
movq (%rdi), %rax
callq *0x28(%rax)
movq 0xca20(%rbx), %rax
movzbl 0x32f(%rax,%r14), %eax
incq 0x7328(%rbx,%rax,8)
jmp 0x3f93
movq 0xca20(%rbx), %rax
movq 0x348(%rax,%r14), %r8
movq 0x370(%rax,%r14), %r9
movzbl 0x32f(%rax,%r14), %eax
subq $0x8, %rsp
movq %rbx, %rdi
movl %ebp, %esi
movl %r12d, %edx
movl $0x10, %ecx
pushq $0x0
pushq %rax
pushq $0x0
callq 0x1385c
addq $0x20, %rsp
movq 0xca20(%rbx), %rsi
movzbl 0x32f(%rsi,%r14), %eax
movq 0x18(%rsp), %rdx
movq %rdx, %rcx
shlq $0x5, %rcx
addq %rbx, %rcx
incq 0x10328(%rcx,%rax,8)
incq 0x102e8(%rcx,%rax,8)
movl 0x8(%rsi,%r14), %eax
cmpl 0x7398(%rbx), %eax
jge 0x3b6e
addq %r14, %rsi
xorl %eax, %eax
cmpb $0x0, (%rsi)
sete %al
leaq (%rbx,%rax,8), %rax
movq 0x8(%rax,%rdx,8), %rdi
movq (%rdi), %rax
callq *0x18(%rax)
addq 0xca20(%rbx), %r14
movq %r15, %rdi
movq %r14, %rsi
callq 0xc3e6
decl 0xc9c0(%rbx)
movq %rbx, %rdi
addq $0x3a8, %rsp            # imm = 0x3A8
popq %rbx
popq %r12
popq %r13
popq %r14
popq %r15
popq %rbp
jmp 0x3fe4
cmpb $0x2, %al
je 0x3cd1
leaq 0x104b9(%rip), %rdi     # 0x14067
leaq 0x104b4(%rip), %rsi     # 0x14069
leaq 0x104ba(%rip), %rcx     # 0x14076
movl $0x65, %edx
callq 0x3160
xorl %eax, %eax
leaq 0x40(%rsp), %r15
movl %eax, -0x15(%r15)
movl %eax, -0x18(%r15)
movl $0xffff00, 0x314(%r15) # imm = 0xFFFF00
pcmpeqd %xmm0, %xmm0
movdqu %xmm0, -0x10(%r15)
movl $0x314, %edx            # imm = 0x314
movq %r15, %rdi
xorl %esi, %esi
callq 0x3130
movl $0x1, 0x318(%r15)
pxor %xmm0, %xmm0
movdqu %xmm0, 0x31c(%r15)
movdqu %xmm0, 0x32c(%r15)
xorl %eax, %eax
movl %eax, 0x33c(%r15)
movdqu %xmm0, 0x348(%r15)
movq %rax, 0x358(%r15)
xorl %edx, %edx
movq $-0x1, 0x360(%r15)
movl 0x7398(%rbx), %eax
addl %eax, %eax
movl %eax, -0x10(%r15)
movl %ebp, 0x318(%r15)
movq 0x7390(%rbx), %rax
movq 0x10(%rsp), %rcx
movq (%rax,%rcx,8), %rax
movq 0x8(%rsp), %rcx
movups 0x18(%rax,%rcx), %xmm0
movups %xmm0, 0x328(%r15)
movq 0x30(%rax,%rcx), %rax
movq %rax, 0x348(%r15)
movq 0xca20(%rbx), %rax
movq 0x368(%rax,%r14), %rax
movq %rax, 0x350(%r15)
movq %rdx, 0x358(%r15)
movb $0x3, 0x317(%r15)
movq 0x18(%rsp), %rax
leaq 0x7d20e(%rip), %rcx     # 0x80ec0
movq (%rcx,%rax,8), %rax
movq %rax, 0x360(%r15)
movq 0x18(%rbx), %rdi
movq (%rdi), %rax
leaq 0x28(%rsp), %rsi
callq *0x8(%rax)
movq 0x20(%rsp), %r15
cmpb $0x4, 0x73a4(%rbx)
jne 0x3d21
movq 0xca20(%rbx), %rax
movq 0x348(%rax,%r14), %rsi
xorl %r8d, %r8d
cmpb $0x2, 0x32f(%rax,%r14)
sete %r8b
movq 0x7390(%rbx), %rax
movq 0x10(%rsp), %rcx
movq (%rax,%rcx,8), %rax
movq 0x8(%rsp), %rcx
movq 0x20(%rax,%rcx), %r9
movq %rbx, %rdi
movl %r12d, %edx
movl %r13d, %ecx
callq 0x1399c
cmpb $0x5, 0x73a4(%rbx)
jne 0x3d71
movq 0xca20(%rbx), %rax
movq 0x348(%rax,%r14), %rsi
xorl %r8d, %r8d
cmpb $0x2, 0x32f(%rax,%r14)
sete %r8b
movq 0x7390(%rbx), %rax
movq 0x10(%rsp), %rcx
movq (%rax,%rcx,8), %rax
movq 0x8(%rsp), %rcx
movq 0x20(%rax,%rcx), %r9
movq %rbx, %rdi
movl %r12d, %edx
movl %r13d, %ecx
callq 0x13994
cmpb $0x6, 0x73a4(%rbx)
movq 0xca20(%rbx), %rcx
movq 0x348(%rcx,%r14), %r8
movq 0x370(%rcx,%r14), %r9
movq 0x7390(%rbx), %rax
movq 0x10(%rsp), %rdx
movq (%rax,%rdx,8), %rax
movq 0x8(%rsp), %rdx
movq 0x20(%rax,%rdx), %rax
movzbl 0x32f(%rcx,%r14), %r10d
jne 0x3dcf
subq $0x8, %rsp
movq %rbx, %rdi
movl %ebp, %esi
movl %r12d, %edx
movl %r13d, %ecx
pushq $0x0
pushq %r10
pushq %rax
callq 0x1385c
jmp 0x3de8
subq $0x8, %rsp
movq %rbx, %rdi
movl %ebp, %esi
movl %r12d, %edx
movl %r13d, %ecx
pushq $0x0
pushq %r10
pushq %rax
callq 0x137be
addq $0x20, %rsp
movq 0xca20(%rbx), %rcx
movzbl 0x32f(%rcx,%r14), %eax
movq 0x18(%rsp), %rdx
shlq $0x5, %rdx
addq %rbx, %rdx
incq 0x10328(%rdx,%rax,8)
addq %r14, %rcx
incq 0x102e8(%rdx,%rax,8)
movq %rbx, %rdi
movl %r12d, %esi
movl %r13d, %edx
callq 0x4044
cmpb $0x4, 0x73a4(%rbx)
jne 0x3e5e
movq 0xca20(%rbx), %rax
cmpb $0x1, 0x32f(%rax,%r14)
jne 0x3e5e
movq 0x7390(%rbx), %rax
movq 0x10(%rsp), %rcx
movq (%rax,%rcx,8), %rax
movq 0x8(%rsp), %rcx
movb $0x1, 0x2(%rax,%rcx)
movq 0xca20(%rbx), %rsi
movl 0x8(%rsi,%r14), %eax
cmpl 0x7398(%rbx), %eax
jge 0x3e91
addq %r14, %rsi
xorl %eax, %eax
cmpb $0x0, (%rsi)
sete %al
leaq (%rbx,%rax,8), %rax
movq 0x18(%rsp), %rcx
movq 0x8(%rax,%rcx,8), %rdi
movq (%rdi), %rax
callq *0x18(%rax)
movzbl 0x73a4(%rbx), %eax
cmpq $0x4, %rax
ja 0x3f73
leaq 0x1015b(%rip), %rcx     # 0x14004
movslq (%rcx,%rax,4), %rax
addq %rcx, %rax
jmpq *%rax
movq 0x7390(%rbx), %rax
movq 0x10(%rsp), %rcx
movq (%rax,%rcx,8), %rax
movq 0x8(%rsp), %rcx
movq 0x30(%rax,%rcx), %rax
movq 0xca20(%rbx), %rsi
movq %rax, 0x350(%rsi,%r14)
jmp 0x3f28
movl 0xe65c(%rbx), %eax
cmpl 0xe648(%rbx), %eax
jae 0x3f73
leaq 0xe628(%rbx), %rdi
movq 0xca20(%rbx), %rsi
jmp 0x3f3d
movq 0x7390(%rbx), %rax
movq 0x10(%rsp), %rcx
movq (%rax,%rcx,8), %rax
movq 0x8(%rsp), %rcx
movq 0x30(%rax,%rcx), %rax
movq 0xca20(%rbx), %rsi
movq %rax, 0x358(%rsi,%r14)
movl 0xe65c(%rbx), %eax
cmpl 0xe648(%rbx), %eax
jae 0x3f73
leaq 0xe628(%rbx), %rdi
addq %r14, %rsi
callq 0xc376
jmp 0x3f73
movq 0xca20(%rbx), %rsi
cmpb $0x2, 0x32f(%rsi,%r14)
je 0x3f73
movl 0xe65c(%rbx), %eax
cmpl 0xe648(%rbx), %eax
jae 0x3f73
addq %r14, %rsi
leaq 0xe628(%rbx), %rdi
jmp 0x3f40
addq 0xca20(%rbx), %r14
movq %r15, %rdi
movq %r14, %rsi
callq 0xc3e6
decl 0xc9c0(%rbx)
movq %rbx, %rdi
callq 0x3fe4
addq $0x3a8, %rsp            # imm = 0x3A8
popq %rbx
popq %r12
popq %r13
popq %r14
popq %r15
popq %rbp
retq
leaq 0x100bb(%rip), %rdi     # 0x14067
leaq 0x100b6(%rip), %rsi     # 0x14069
leaq 0x100bc(%rip), %rcx     # 0x14076
movl $0x10, %edx
callq 0x3160