// File: dsesami[P]superscalar-processor-model/main.cc
// Function: main
int main(int argc, char ** argv) {
    if(argc != 7) {
        cout << "Invalid amount of arguments for 'sim_ds'. Please include 6 " <<
                "parameters of the format <ROB_SIZE> <IQ_SIZE> <WIDTH> " <<
                "<CACHE_SIZE> <P> <TRACE_FILE>." << endl;
        return 1;
    }

    ROBSIZE    = atoi(argv[1]), // Max # of entries within Reorder Buffer
    IQ_SIZE    = atoi(argv[2]), // Max # of entries within Issue Queue
    WIDTH      = atoi(argv[3]), // Superscalar width of all pipeline stages (minus WB)
    CACHE_SIZE = atoi(argv[4]), // Size of instruction cache in bytes
    P          = atoi(argv[5]); // Prefetching flag
    TRACE_FILE =      argv[6] ; // Name of trace file

    dyn_instr_count   = 0,   // Dynamic instruction count
    cycles            = 0;   // Total number of cycles. Always at least 1.
    double ipc        = 0;   // Average instructions per cycle

    infile.open(TRACE_FILE);

    ROB.resize(ROBSIZE);
    IQ.resize(IQ_SIZE);

    // Pipeline routine
    do {
        retire();
        //cout << "1" << endl;
        writeback();
        //cout << "2" << endl;
        execute();
        //cout << "3" << endl;
        issue();
        //cout << "4" << endl;
        dispatch();
        //cout << "5" << endl;
        regRead();
        //cout << "6" << endl;
        rename();
        //cout << "7" << endl;
        decode();
        //cout << "8" << endl;
        FE_continue = fetch();
        //cout << "9" << endl;
    }
    while (advance_cycle());

    ipc = (double) dyn_instr_count / (double) cycles;

    cout << "# === Simulator Command =========" << endl
         << "# ./sim_ds "  << argv[1] << " " <<
            argv[2] << " " << argv[3] << " " <<
            argv[4] << " " << argv[5] << " " <<
            argv[6] << endl;
    cout << "# === Processor Configuration ===" << endl;
    cout << "# ROB_SIZE  = "        << argv[1]  << endl;
    cout << "# IQ_SIZE   = "        << argv[2]  << endl;
    cout << "# WIDTH     = "        << argv[3]  << endl;
    cout << "# CACHE_SIZE    = "    << argv[4]  << endl;
    cout << "# PREFETCHING   = "    << argv[5]  << endl;
    cout << "# === Simulation Results ========" << endl;
    cout << "# Dynamic Instruction Count      = " << dyn_instr_count << endl;
    cout << "# Cycles                         = " << cycles          << endl;
    cout << "# Instructions Per Cycle (IPC)   = " << fixed << setprecision(2) << ipc             << endl;

    return 0;
}

// Assembly:
pushq %rbp
movq %rsp, %rbp
subq $0x30, %rsp
movl $0x0, -0x4(%rbp)
movl %edi, -0x8(%rbp)
movq %rsi, -0x10(%rbp)
cmpl $0x7, -0x8(%rbp)
je 0x2928
movq 0xe6f5(%rip), %rdi      # 0x10fd8
leaq 0x871a(%rip), %rsi      # 0xb004
callq 0x2190
movq %rax, %rdi
leaq 0x8747(%rip), %rsi      # 0xb040
callq 0x2190
movq %rax, %rdi
leaq 0x876f(%rip), %rsi      # 0xb077
callq 0x2190
movq %rax, %rdi
movq 0xe6b1(%rip), %rsi      # 0x10fc8
callq 0x21c0
movl $0x1, -0x4(%rbp)
jmp 0x2d38
movq -0x10(%rbp), %rax
movq 0x8(%rax), %rdi
callq 0x2260
movl %eax, 0xe881(%rip)      # 0x111bc
movq -0x10(%rbp), %rax
movq 0x10(%rax), %rdi
callq 0x2260
movl %eax, 0xe872(%rip)      # 0x111c0
movq -0x10(%rbp), %rax
movq 0x18(%rax), %rdi
callq 0x2260
movl %eax, 0xe863(%rip)      # 0x111c4
movq -0x10(%rbp), %rax
movq 0x20(%rax), %rdi
callq 0x2260
movl %eax, 0xe854(%rip)      # 0x111c8
movq -0x10(%rbp), %rax
movq 0x28(%rax), %rdi
callq 0x2260
movl %eax, 0xe845(%rip)      # 0x111cc
movq -0x10(%rbp), %rax
movq 0x30(%rax), %rax
movq %rax, 0xe842(%rip)      # 0x111d8
movl $0x0, 0xe830(%rip)      # 0x111d0
movl $0x0, 0xe82a(%rip)      # 0x111d4
xorps %xmm0, %xmm0
movsd %xmm0, -0x18(%rbp)
movq 0xe81f(%rip), %rsi      # 0x111d8
leaq 0xe820(%rip), %rdi      # 0x111e0
movl $0x8, %edx
callq 0x2130
movl 0xe7ec(%rip), %eax      # 0x111bc
movl %eax, %esi
leaq 0xea0f(%rip), %rdi      # 0x113e8
callq 0x3590
movl 0xe7dc(%rip), %eax      # 0x111c0
movl %eax, %esi
leaq 0xea2b(%rip), %rdi      # 0x11418
callq 0x3620
callq 0x9b10
callq 0x9840
callq 0x8bd0
callq 0x8170
callq 0x7de0
callq 0x7b40
callq 0x75c0
callq 0x7200
callq 0x64e0
movl %eax, 0xea23(%rip)      # 0x11448
callq 0x2d50
testb $0x1, %al
jne 0x29f2
movl 0xe79c(%rip), %eax      # 0x111d0
cvtsi2sd %rax, %xmm0
movl 0xe795(%rip), %eax      # 0x111d4
cvtsi2sd %rax, %xmm1
divsd %xmm1, %xmm0
movsd %xmm0, -0x18(%rbp)
movq 0xe584(%rip), %rdi      # 0x10fd8
leaq 0x863b(%rip), %rsi      # 0xb096
callq 0x2190
movq %rax, %rdi
movq 0xe55e(%rip), %rsi      # 0x10fc8
callq 0x21c0
movq %rax, %rdi
leaq 0x863f(%rip), %rsi      # 0xb0b8
callq 0x2190
movq %rax, %rdi
movq -0x10(%rbp), %rax
movq 0x8(%rax), %rsi
callq 0x2190
movq %rax, %rdi
leaq 0x8942(%rip), %rsi      # 0xb3da
callq 0x2190
movq %rax, %rdi
movq -0x10(%rbp), %rax
movq 0x10(%rax), %rsi
callq 0x2190
movq %rax, %rdi
leaq 0x8923(%rip), %rsi      # 0xb3da
callq 0x2190
movq %rax, %rdi
movq -0x10(%rbp), %rax
movq 0x18(%rax), %rsi
callq 0x2190
movq %rax, %rdi
leaq 0x8904(%rip), %rsi      # 0xb3da
callq 0x2190
movq %rax, %rdi
movq -0x10(%rbp), %rax
movq 0x20(%rax), %rsi
callq 0x2190
movq %rax, %rdi
leaq 0x88e5(%rip), %rsi      # 0xb3da
callq 0x2190
movq %rax, %rdi
movq -0x10(%rbp), %rax
movq 0x28(%rax), %rsi
callq 0x2190
movq %rax, %rdi
leaq 0x88c6(%rip), %rsi      # 0xb3da
callq 0x2190
movq %rax, %rdi
movq -0x10(%rbp), %rax
movq 0x30(%rax), %rsi
callq 0x2190
movq %rax, %rdi
movq 0xe495(%rip), %rsi      # 0x10fc8
callq 0x21c0
movq 0xe499(%rip), %rdi      # 0x10fd8
leaq 0x857e(%rip), %rsi      # 0xb0c4
callq 0x2190
movq %rax, %rdi
movq 0xe473(%rip), %rsi      # 0x10fc8
callq 0x21c0
movq 0xe477(%rip), %rdi      # 0x10fd8
leaq 0x857e(%rip), %rsi      # 0xb0e6
callq 0x2190
movq %rax, %rdi
movq -0x10(%rbp), %rax
movq 0x8(%rax), %rsi
callq 0x2190
movq %rax, %rdi
movq 0xe441(%rip), %rsi      # 0x10fc8
callq 0x21c0
movq 0xe445(%rip), %rdi      # 0x10fd8
leaq 0x855b(%rip), %rsi      # 0xb0f5
callq 0x2190
movq %rax, %rdi
movq -0x10(%rbp), %rax
movq 0x10(%rax), %rsi
callq 0x2190
movq %rax, %rdi
movq 0xe40f(%rip), %rsi      # 0x10fc8
callq 0x21c0
movq 0xe413(%rip), %rdi      # 0x10fd8
leaq 0x8538(%rip), %rsi      # 0xb104
callq 0x2190
movq %rax, %rdi
movq -0x10(%rbp), %rax
movq 0x18(%rax), %rsi
callq 0x2190
movq %rax, %rdi
movq 0xe3dd(%rip), %rsi      # 0x10fc8
callq 0x21c0
movq 0xe3e1(%rip), %rdi      # 0x10fd8
leaq 0x8515(%rip), %rsi      # 0xb113
callq 0x2190
movq %rax, %rdi
movq -0x10(%rbp), %rax
movq 0x20(%rax), %rsi
callq 0x2190
movq %rax, %rdi
movq 0xe3ab(%rip), %rsi      # 0x10fc8
callq 0x21c0
movq 0xe3af(%rip), %rdi      # 0x10fd8
leaq 0x84f6(%rip), %rsi      # 0xb126
callq 0x2190
movq %rax, %rdi
movq -0x10(%rbp), %rax
movq 0x28(%rax), %rsi
callq 0x2190
movq %rax, %rdi
movq 0xe379(%rip), %rsi      # 0x10fc8
callq 0x21c0
movq 0xe37d(%rip), %rdi      # 0x10fd8
leaq 0x84d7(%rip), %rsi      # 0xb139
callq 0x2190
movq %rax, %rdi
movq 0xe357(%rip), %rsi      # 0x10fc8
callq 0x21c0
movq 0xe35b(%rip), %rdi      # 0x10fd8
leaq 0x84d7(%rip), %rsi      # 0xb15b
callq 0x2190
movq %rax, %rdi
movl 0xe53e(%rip), %esi      # 0x111d0
callq 0x2210
movq %rax, %rdi
movq 0xe327(%rip), %rsi      # 0x10fc8
callq 0x21c0
movq 0xe32b(%rip), %rdi      # 0x10fd8
leaq 0x84cb(%rip), %rsi      # 0xb17f
callq 0x2190
movq %rax, %rdi
movl 0xe512(%rip), %esi      # 0x111d4
callq 0x2210
movq %rax, %rdi
movq 0xe2f7(%rip), %rsi      # 0x10fc8
callq 0x21c0
movq 0xe2fb(%rip), %rdi      # 0x10fd8
leaq 0x84bf(%rip), %rsi      # 0xb1a3
callq 0x2190
movq %rax, %rdi
leaq 0x9bd(%rip), %rsi       # 0x36b0
callq 0x2070
movq %rax, -0x28(%rbp)
movl $0x2, %edi
callq 0x36e0
movq -0x28(%rbp), %rdi
movl %eax, -0x1c(%rbp)
movl -0x1c(%rbp), %esi
callq 0x2280
movq %rax, %rdi
movsd -0x18(%rbp), %xmm0
callq 0x2300
movq %rax, %rdi
movq 0xe29c(%rip), %rsi      # 0x10fc8
callq 0x21c0
movl $0x0, -0x4(%rbp)
movl -0x4(%rbp), %eax
addq $0x30, %rsp
popq %rbp
retq
nopw %cs:(%rax,%rax)