// File: NishadSaraf[P]Championship-Simulator/src/cache.cc
// Function: CACHE::add_wq(PACKET*)
int CACHE::add_wq(PACKET *packet)
{
    // check for duplicates in the write queue
    int index = WQ.check_queue(packet);
    if (index != -1) {

        WQ.MERGED++;
        WQ.ACCESS++;

        return index; // merged index
    }

    // sanity check
    if (WQ.occupancy >= WQ.SIZE)
        assert(0);

    // if there is no duplicate, add it to the write queue
    index = WQ.tail;
    if (WQ.entry[index].address != 0) {
        cerr << "[" << NAME << "_ERROR] " << __func__ << " is not empty index: " << index;
        cerr << " address: " << hex << WQ.entry[index].address;
        cerr << " full_addr: " << WQ.entry[index].full_addr << dec << endl;
        assert(0);
    }

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

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

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

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

    WQ.TO_CACHE++;
    WQ.ACCESS++;

    return -1;
}

// Assembly:
subq $0x28, %rsp
movq %rdi, 0x18(%rsp)
movq %rsi, 0x10(%rsp)
movq 0x18(%rsp), %rdi
movq %rdi, (%rsp)
addq $0x73a8, %rdi           # imm = 0x73A8
movq 0x10(%rsp), %rsi
callq 0x14da0
movl %eax, 0xc(%rsp)
cmpl $-0x1, 0xc(%rsp)
je 0x88d8
movq (%rsp), %rax
movq 0x7418(%rax), %rcx
addq $0x1, %rcx
movq %rcx, 0x7418(%rax)
movq 0x7408(%rax), %rcx
addq $0x1, %rcx
movq %rcx, 0x7408(%rax)
movl 0xc(%rsp), %eax
movl %eax, 0x24(%rsp)
jmp 0x8ba2
movq (%rsp), %rcx
movl 0x73dc(%rcx), %eax
cmpl 0x73c8(%rcx), %eax
jb 0x8909
leaq 0x1a713(%rip), %rdi     # 0x23004
leaq 0x1a70e(%rip), %rsi     # 0x23006
movl $0x430, %edx            # imm = 0x430
leaq 0x1a8e2(%rip), %rcx     # 0x231e6
callq 0x3160
movq (%rsp), %rax
movl 0x73d8(%rax), %ecx
movl %ecx, 0xc(%rsp)
movq 0x7440(%rax), %rax
movslq 0xc(%rsp), %rcx
imulq $0x380, %rcx, %rcx      # imm = 0x380
addq %rcx, %rax
cmpq $0x0, 0x340(%rax)
je 0x8a5e
movq 0x206ae(%rip), %rdi     # 0x28ff0
leaq 0x1a6e4(%rip), %rsi     # 0x2302d
callq 0x3220
movq (%rsp), %rsi
movq %rax, %rdi
addq $0x7350, %rsi           # imm = 0x7350
callq 0x31c0
movq %rax, %rdi
leaq 0x1b27a(%rip), %rsi     # 0x23be5
callq 0x3220
movq %rax, %rdi
leaq 0x1a890(%rip), %rsi     # 0x2320a
callq 0x3220
movq %rax, %rdi
leaq 0x1a847(%rip), %rsi     # 0x231d0
callq 0x3220
movq %rax, %rdi
movl 0xc(%rsp), %esi
callq 0x33b0
movq 0x2064f(%rip), %rdi     # 0x28ff0
leaq 0x1a778(%rip), %rsi     # 0x23120
callq 0x3220
movq %rax, %rdi
leaq 0xef9(%rip), %rsi       # 0x98b0
callq 0x30d0
movq %rax, %rdi
movq (%rsp), %rax
movq 0x7440(%rax), %rax
movslq 0xc(%rsp), %rcx
imulq $0x380, %rcx, %rcx      # imm = 0x380
addq %rcx, %rax
movq 0x340(%rax), %rsi
callq 0x3080
movq 0x20604(%rip), %rdi     # 0x28ff0
leaq 0x1a738(%rip), %rsi     # 0x2312b
callq 0x3220
movq %rax, %rdi
movq (%rsp), %rax
movq 0x7440(%rax), %rax
movslq 0xc(%rsp), %rcx
imulq $0x380, %rcx, %rcx      # imm = 0x380
addq %rcx, %rax
movq 0x348(%rax), %rsi
callq 0x3080
movq %rax, %rdi
leaq 0xea5(%rip), %rsi       # 0x98d0
callq 0x30d0
movq %rax, %rdi
movq 0x2057e(%rip), %rsi     # 0x28fb8
callq 0x3250
leaq 0x1a5be(%rip), %rdi     # 0x23004
leaq 0x1a5b9(%rip), %rsi     # 0x23006
movl $0x438, %edx            # imm = 0x438
leaq 0x1a78d(%rip), %rcx     # 0x231e6
callq 0x3160
movq (%rsp), %rax
movq 0x7440(%rax), %rdi
movslq 0xc(%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
movq 0x7440(%rax), %rax
movslq 0xc(%rsp), %rcx
imulq $0x380, %rcx, %rcx      # imm = 0x380
addq %rcx, %rax
movq 0x378(%rax), %rax
movq 0x10(%rsp), %rcx
movl 0x330(%rcx), %ecx
movl %ecx, %edx
leaq 0x87404(%rip), %rcx     # 0x8fec0
cmpq (%rcx,%rdx,8), %rax
jae 0x8b06
movq (%rsp), %rax
movq 0x10(%rsp), %rcx
movl 0x330(%rcx), %ecx
movl %ecx, %edx
leaq 0x873e6(%rip), %rcx     # 0x8fec0
movq (%rcx,%rdx,8), %rcx
movl 0x738c(%rax), %edx
addq %rdx, %rcx
movq 0x7440(%rax), %rax
movslq 0xc(%rsp), %rdx
imulq $0x380, %rdx, %rdx      # imm = 0x380
addq %rdx, %rax
movq %rcx, 0x378(%rax)
jmp 0x8b34
movq (%rsp), %rax
movl 0x738c(%rax), %ecx
movq 0x7440(%rax), %rax
movslq 0xc(%rsp), %rdx
imulq $0x380, %rdx, %rdx      # imm = 0x380
addq %rdx, %rax
addq 0x378(%rax), %rcx
movq %rcx, 0x378(%rax)
movq (%rsp), %rcx
movl 0x73dc(%rcx), %eax
addl $0x1, %eax
movl %eax, 0x73dc(%rcx)
movl 0x73d8(%rcx), %eax
addl $0x1, %eax
movl %eax, 0x73d8(%rcx)
movl 0x73d8(%rcx), %eax
cmpl 0x73c8(%rcx), %eax
jb 0x8b72
movq (%rsp), %rax
movl $0x0, 0x73d8(%rax)
movq (%rsp), %rax
movq 0x7420(%rax), %rcx
addq $0x1, %rcx
movq %rcx, 0x7420(%rax)
movq 0x7408(%rax), %rcx
addq $0x1, %rcx
movq %rcx, 0x7408(%rax)
movl $0xffffffff, 0x24(%rsp) # imm = 0xFFFFFFFF
movl 0x24(%rsp), %eax
addq $0x28, %rsp
retq
nopl (%rax,%rax)