// File: /workspace/github_cpp_makefile_star2_O2/NishadSaraf[P]Championship-Simulator/src/cache.cc
// Function: CACHE::add_pq(PACKET*)
int CACHE::add_pq(PACKET *packet)
{
    // check for the latest wirtebacks in the write queue
    int wq_index = WQ.check_queue(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);
        }

        HIT[packet->type]++;
        ACCESS[packet->type]++;

        WQ.FORWARD++;
        PQ.ACCESS++;

        return -1;
    }

    // check for duplicates in the PQ
    int index = PQ.check_queue(packet);
    if (index != -1) {
        if (packet->fill_level < PQ.entry[index].fill_level)
            PQ.entry[index].fill_level = packet->fill_level;

        PQ.MERGED++;
        PQ.ACCESS++;

        return index; // merged index
    }

    // check occupancy
    if (PQ.occupancy == PQ_SIZE) {
        PQ.FULL++;

        DP ( if (warmup_complete[packet->cpu]) {
        cout << "[" << NAME << "] cannot process add_pq since it is full" << endl; });
        return -2; // cannot handle this request
    }

    // if there is no duplicate, add it to PQ
    index = PQ.tail;

#ifdef SANITY_CHECK
    if (PQ.entry[index].address != 0) {
        cerr << "[" << NAME << "_ERROR] " << __func__ << " is not empty index: " << index;
        cerr << " address: " << hex << PQ.entry[index].address;
        cerr << " full_addr: " << PQ.entry[index].full_addr << dec << endl;
        assert(0);
    }
#endif

    memcpy(&PQ.entry[index], packet, sizeof(PACKET));

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

    PQ.occupancy++;
    PQ.tail++;
    if (PQ.tail >= PQ.SIZE)
        PQ.tail = 0;

    DP ( if (warmup_complete[PQ.entry[index].cpu]) {
    cout << "[" << NAME << "_PQ] " <<  __func__ << " instr_id: " << PQ.entry[index].instr_id << " address: " << hex << PQ.entry[index].address;
    cout << " full_addr: " << PQ.entry[index].full_addr << dec;
    cout << " type: " << +PQ.entry[index].type << " head: " << PQ.head << " tail: " << PQ.tail << " occupancy: " << PQ.occupancy;
    cout << " event: " << PQ.entry[index].event_cycle << " current: " << current_core_cycle[PQ.entry[index].cpu] << endl; });

    if (packet->address == 0)
        assert(0);

    PQ.TO_CACHE++;
    PQ.ACCESS++;

    return -1;
}

// Assembly:
pushq %r15
pushq %r14
pushq %r12
pushq %rbx
pushq %rax
movq %rsi, %r14
movq %rdi, %rbx
addq $0x73a8, %rdi           # imm = 0x73A8
callq 0x9b10
cmpl $-0x1, %eax
je 0x4fa1
movl 0x8(%r14), %ecx
cmpl 0x7398(%rbx), %ecx
jge 0x4f68
movq 0x7440(%rbx), %rcx
cltq
imulq $0x380, %rax, %rax      # imm = 0x380
movq 0x360(%rcx,%rax), %rax
movq %rax, 0x360(%r14)
xorl %eax, %eax
cmpb $0x0, (%r14)
sete %al
movl 0x330(%r14), %ecx
leaq (%rbx,%rax,8), %rax
movq 0x8(%rax,%rcx,8), %rdi
movq (%rdi), %rax
movq %r14, %rsi
callq *0x18(%rax)
movzbl 0x32f(%r14), %eax
incq 0x72c8(%rbx,%rax,8)
incq 0x72a8(%rbx,%rax,8)
pushq $-0x1
popq %rax
movl $0x7410, %ecx           # imm = 0x7410
incq (%rbx,%rcx)
movl $0xad48, %ecx           # imm = 0xAD48
incq (%rbx,%rcx)
addq $0x8, %rsp
popq %rbx
popq %r12
popq %r14
popq %r15
retq
leaq 0xace8(%rbx), %rdi
movq %r14, %rsi
callq 0x9b10
cmpl $-0x1, %eax
je 0x4fe0
movl 0x8(%r14), %edx
movq 0xad80(%rbx), %rsi
movslq %eax, %rcx
imulq $0x380, %rcx, %rdi      # imm = 0x380
movl $0xad58, %ecx           # imm = 0xAD58
cmpl 0x8(%rsi,%rdi), %edx
jge 0x4f88
addq %rdi, %rsi
addq $0x8, %rsi
movl %edx, (%rsi)
jmp 0x4f88
movl 0xad1c(%rbx), %eax
cmpl 0x7384(%rbx), %eax
jne 0x4ff8
pushq $-0x2
popq %rax
movl $0xad78, %ecx           # imm = 0xAD78
jmp 0x4f91
movslq 0xad18(%rbx), %r15
movq 0xad80(%rbx), %rdi
imulq $0x380, %r15, %r12      # imm = 0x380
cmpq $0x0, 0x340(%rdi,%r12)
jne 0x509f
addq %r12, %rdi
movl $0x380, %edx            # imm = 0x380
movq %r14, %rsi
callq 0x21b0
movq 0xad80(%rbx), %rax
movq 0x378(%rax,%r12), %rcx
movl 0x330(%r14), %edx
leaq 0x77e67(%rip), %rsi     # 0x7ceb0
movq (%rsi,%rdx,8), %rdx
movl 0x738c(%rbx), %esi
cmpq %rdx, %rcx
cmovaq %rcx, %rdx
addq %rsi, %rdx
movq %rdx, 0x378(%rax,%r12)
incl 0xad1c(%rbx)
movl 0xad18(%rbx), %eax
incl %eax
xorl %ecx, %ecx
cmpl 0xad08(%rbx), %eax
cmovbl %eax, %ecx
movl %ecx, 0xad18(%rbx)
cmpq $0x0, 0x340(%r14)
je 0x5199
pushq $-0x1
popq %rax
movl $0xad60, %ecx           # imm = 0xAD60
jmp 0x4f88
movq 0x10f4a(%rip), %r14     # 0x15ff0
leaq 0xafe3(%rip), %rsi      # 0x10090
movq %r14, %rdi
callq 0x2230
leaq 0x7350(%rbx), %rsi
movq %rax, %rdi
callq 0x21d0
leaq 0xbb53(%rip), %rsi      # 0x10c1e
movq %rax, %rdi
callq 0x2230
leaq 0xb19a(%rip), %rsi      # 0x10274
movq %rax, %rdi
callq 0x2230
leaq 0xb14a(%rip), %rsi      # 0x10233
movq %rax, %rdi
callq 0x2230
movq %rax, %rdi
movl %r15d, %esi
callq 0x2390
leaq 0xb080(%rip), %rsi      # 0x10183
movq %r14, %rdi
callq 0x2230
movq (%rax), %rcx
movq -0x18(%rcx), %rcx
movl 0x18(%rax,%rcx), %edx
andl $-0x4b, %edx
orl $0x8, %edx
movl %edx, 0x18(%rax,%rcx)
movq 0xad80(%rbx), %rcx
movq 0x340(%rcx,%r12), %rsi
movq %rax, %rdi
callq 0x2080
leaq 0xb050(%rip), %rsi      # 0x1018e
movq %r14, %rdi
callq 0x2230
movq 0xad80(%rbx), %rcx
movq 0x348(%rcx,%r12), %rsi
movq %rax, %rdi
callq 0x2080
movq (%rax), %rcx
movq -0x18(%rcx), %rcx
movl 0x18(%rax,%rcx), %edx
andl $-0x4b, %edx
orl $0x2, %edx
movl %edx, 0x18(%rax,%rcx)
movq %rax, %rdi
callq 0x2110
leaq 0xaee6(%rip), %rdi      # 0x10067
leaq 0xaee1(%rip), %rsi      # 0x10069
leaq 0xb0ec(%rip), %rcx      # 0x1027b
movl $0x4c9, %edx            # imm = 0x4C9
callq 0x2160
leaq 0xaec7(%rip), %rdi      # 0x10067
leaq 0xaec2(%rip), %rsi      # 0x10069
leaq 0xb0cd(%rip), %rcx      # 0x1027b
movl $0x4e1, %edx            # imm = 0x4E1
callq 0x2160