// File: NishadSaraf[P]Championship-Simulator/src/dram_controller.cc
// Function: MEMORY_CONTROLLER::add_wq(PACKET*)
int MEMORY_CONTROLLER::add_wq(PACKET *packet)
{
    // simply drop write requests before the warmup
    if (all_warmup_complete < NUM_CPUS)
        return -1;

    // check for duplicates in the write queue
    //int index = WQ.check_queue(packet);
    int index = check_dram_queue(&WQ, packet);
    if (index != -1)
        return index; // merged index

    // search for the empty index
    for (index=0; index<DRAM_WQ_SIZE; index++) {
        if (WQ.entry[index].address == 0) {
            
            memcpy(&WQ.entry[index], packet, sizeof(PACKET));
            WQ.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 << "_WQ] " <<  __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: " << WQ.occupancy << " current: " << current_core_cycle[packet->cpu] << " event: " << packet->event_cycle << endl; });

            break;
        }
    }

    /*
    //if (WQ.occupancy == 1) { // queue was empty and we are adding the first entry

        // update event time
        WQ.event_cycle = packet->event_cycle;
        WQ.event_cpu = packet->cpu;

        //if (warmup_complete[packet->cpu]) 
        //    DP(cout << "[" << NAME << "_WQ] " << __func__ << " update event_cpu: " << WQ.event_cpu << " event_cycle: " << WQ.event_cycle << endl;)
    //}
    */
    update_schedule_cycle(&WQ);

    return -1;
}

// Assembly:
subq $0x28, %rsp
movq %rdi, 0x18(%rsp)
movq %rsi, 0x10(%rsp)
movq 0x18(%rsp), %rax
movq %rax, (%rsp)
leaq 0x147c5(%rip), %rax     # 0x29343
movzbl (%rax), %eax
cmpl $0x1, %eax
jge 0x14b93
movl $0xffffffff, 0x24(%rsp) # imm = 0xFFFFFFFF
jmp 0x14c5e
movq (%rsp), %rdi
movq %rdi, %rsi
addq $0x8258, %rsi           # imm = 0x8258
movq 0x10(%rsp), %rdx
callq 0x14ae0
movl %eax, 0xc(%rsp)
cmpl $-0x1, 0xc(%rsp)
je 0x14bc3
movl 0xc(%rsp), %eax
movl %eax, 0x24(%rsp)
jmp 0x14c5e
movl $0x0, 0xc(%rsp)
cmpl $0x30, 0xc(%rsp)
jge 0x14c43
movq (%rsp), %rax
movq 0x82f0(%rax), %rax
movslq 0xc(%rsp), %rcx
imulq $0x380, %rcx, %rcx      # imm = 0x380
addq %rcx, %rax
cmpq $0x0, 0x340(%rax)
jne 0x14c34
movq (%rsp), %rax
movq 0x82f0(%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
movl 0x828c(%rax), %ecx
addl $0x1, %ecx
movl %ecx, 0x828c(%rax)
jmp 0x14c43
jmp 0x14c36
movl 0xc(%rsp), %eax
addl $0x1, %eax
movl %eax, 0xc(%rsp)
jmp 0x14bcb
movq (%rsp), %rdi
movq %rdi, %rsi
addq $0x8258, %rsi           # imm = 0x8258
callq 0x13530
movl $0xffffffff, 0x24(%rsp) # imm = 0xFFFFFFFF
movl 0x24(%rsp), %eax
addq $0x28, %rsp
retq
nopw (%rax,%rax)