// File: /workspace/github_cpp_makefile_star2_O3/CMU-SAFARI[P]ramulator/src/Main.cpp
// Function: void run_cputrace<ramulator::DDR3>(ramulator::Config const&, ramulator::Memory<ramulator::DDR3, ramulator::Controller>&, std::vector<char const*, std::allocator<char const*>> const&)
void run_cputrace(const Config& configs, Memory<T, Controller>& memory, const std::vector<const char *>& files)
{
    int cpu_tick = configs.get_cpu_tick();
    int mem_tick = configs.get_mem_tick();
    auto send = bind(&Memory<T, Controller>::send, &memory, placeholders::_1);
    Processor proc(configs, files, send, memory);

    long warmup_insts = configs.get_warmup_insts();
    bool is_warming_up = (warmup_insts != 0);

    for(long i = 0; is_warming_up; i++){
        proc.tick();
        Stats::curTick++;
        if (i % cpu_tick == (cpu_tick - 1))
            for (int j = 0; j < mem_tick; j++)
                memory.tick();

        is_warming_up = false;
        for(int c = 0; c < proc.cores.size(); c++){
            if(proc.cores[c]->get_insts() < warmup_insts)
                is_warming_up = true;
        }

        if (is_warming_up && proc.has_reached_limit()) {
            printf("WARNING: The end of the input trace file was reached during warmup. "
                    "Consider changing warmup_insts in the config file. \n");
            break;
        }

    }

    warmup_complete = true;
    printf("Warmup complete! Resetting stats...\n");
    Stats::reset_stats();
    proc.reset_stats();
    assert(proc.get_insts() == 0);

    printf("Starting the simulation...\n");

    int tick_mult = cpu_tick * mem_tick;
    for (long i = 0; ; i++) {
        if (((i % tick_mult) % mem_tick) == 0) { // When the CPU is ticked cpu_tick times,
                                                 // the memory controller should be ticked mem_tick times
            proc.tick();
            Stats::curTick++; // processor clock, global, for Statistics

            if (configs.calc_weighted_speedup()) {
                if (proc.has_reached_limit()) {
                    break;
                }
            } else {
                if (configs.is_early_exit()) {
                    if (proc.finished())
                    break;
                } else {
                if (proc.finished() && (memory.pending_requests() == 0))
                    break;
                }
            }
        }

        if (((i % tick_mult) % cpu_tick) == 0) // TODO_hasan: Better if the processor ticks the memory controller
            memory.tick();

    }
    // This a workaround for statistics set only initially lost in the end
    memory.finish();
    Stats::statlist.printall();
}

// Assembly:
pushq %rbp
pushq %r15
pushq %r14
pushq %r13
pushq %r12
pushq %rbx
subq $0x848, %rsp            # imm = 0x848
movq %rsi, %rbx
movq %rdi, %r14
movslq 0x3c(%rdi), %r15
movl 0x40(%rdi), %eax
movl %eax, 0xc(%rsp)
leaq 0x28(%rsp), %rdi
movq %rdx, %rsi
callq 0x2bbda
xorps %xmm0, %xmm0
movaps %xmm0, 0x50(%rsp)
movaps %xmm0, 0x40(%rsp)
movl $0x18, %edi
callq 0xb2e0
movq $0x21, (%rax)
movq $0x0, 0x8(%rax)
movq %rbx, 0x10(%rax)
leaq 0x40(%rsp), %rcx
movq %rax, (%rcx)
leaq 0xb6dc(%rip), %rax      # 0x2bea6
movq %rax, 0x18(%rcx)
leaq 0xb6e1(%rip), %rax      # 0x2beb6
movq %rax, 0x10(%rcx)
leaq 0x60(%rsp), %rdi
leaq 0x28(%rsp), %rdx
movq %r14, %rsi
movq %rbx, %r8
callq 0x12bc14
movq %r15, 0x10(%rsp)
movq 0x50(%rsp), %rax
testq %rax, %rax
je 0x2080c
leaq 0x40(%rsp), %rdi
movq %rdi, %rsi
movl $0x3, %edx
callq *%rax
movq 0x28(%rsp), %rdi
testq %rdi, %rdi
je 0x20823
movq 0x38(%rsp), %rsi
subq %rdi, %rsi
callq 0xb2f0
movq %r14, 0x18(%rsp)
movq 0x50(%r14), %r13
testq %r13, %r13
je 0x208fa
movq 0x10(%rsp), %r14
leaq -0x1(%r14), %rax
movq %rax, 0x20(%rsp)
xorl %r15d, %r15d
leaq 0x60(%rsp), %rbp
movl $0x1, %r12d
movq %rbp, %rdi
callq 0x12c43e
movl 0xc(%rsp), %ebp
testl %ebp, %ebp
setle %cl
leaq 0x180a8f(%rip), %rax    # 0x1a12f8
incq (%rax)
movq %r15, %rax
cqto
idivq %r14
cmpq 0x20(%rsp), %rdx
setne %al
orb %cl, %al
jne 0x2088d
movq (%rbx), %rax
movq %rbx, %rdi
callq *0x18(%rax)
decl %ebp
jne 0x20880
movq 0x60(%rsp), %rax
cmpq %rax, 0x68(%rsp)
je 0x208fa
xorl %ebp, %ebp
xorl %r14d, %r14d
movq (%rax,%rbp,8), %rdi
callq 0x12cd7e
cmpq %r13, %rax
movzbl %r14b, %r14d
cmovll %r12d, %r14d
incq %rbp
movq 0x60(%rsp), %rax
movq 0x68(%rsp), %rcx
subq %rax, %rcx
sarq $0x3, %rcx
cmpq %rbp, %rcx
ja 0x2089e
testb $0x1, %r14b
je 0x208fa
leaq 0x60(%rsp), %rbp
movq %rbp, %rdi
callq 0x12cd12
movq 0x10(%rsp), %r14
incq %r15
testb %al, %al
je 0x20851
leaq 0x12fe64(%rip), %rdi    # 0x150759
callq 0xb420
movb $0x1, 0x17f9d1(%rip)    # 0x1a02d2
leaq 0x12fec9(%rip), %rdi    # 0x1507d1
callq 0xb420
callq 0x13b494
leaq 0x60(%rsp), %rdi
callq 0x12cd88
leaq 0x60(%rsp), %rdi
callq 0x12cd4c
testq %rax, %rax
movq 0x10(%rsp), %rbp
jne 0x20a0e
leaq 0x12feba(%rip), %rdi    # 0x1507f5
callq 0xb420
movl %ebp, %eax
imull 0xc(%rsp), %eax
movslq %eax, %r12
xorl %r15d, %r15d
movq 0x18(%rsp), %r14
movq %r15, %rax
cqto
idivq %r12
movq %rdx, %r13
movl %r13d, %eax
cltd
idivl 0xc(%rsp)
testl %edx, %edx
jne 0x209aa
leaq 0x60(%rsp), %rdi
callq 0x12c43e
leaq 0x18097e(%rip), %rax    # 0x1a12f8
incq (%rax)
cmpq $0x0, 0x48(%r14)
je 0x20990
leaq 0x60(%rsp), %rdi
callq 0x12cd12
jmp 0x209a6
movq %r14, %rdi
callq 0x2bc5a
testb %al, %al
je 0x209c2
leaq 0x60(%rsp), %rdi
callq 0x12cb5c
testb %al, %al
jne 0x209dd
movl %r13d, %eax
cltd
idivl %ebp
testl %edx, %edx
jne 0x209bd
movq (%rbx), %rax
movq %rbx, %rdi
callq *0x18(%rax)
incq %r15
jmp 0x20952
leaq 0x60(%rsp), %rdi
callq 0x12cb5c
testb %al, %al
je 0x209aa
movq (%rbx), %rax
movq %rbx, %rdi
callq *0x28(%rax)
testl %eax, %eax
jne 0x209aa
movq (%rbx), %rax
movq %rbx, %rdi
callq *0x30(%rax)
leaq 0x1806f3(%rip), %rdi    # 0x1a10e0
callq 0x2bd4e
leaq 0x60(%rsp), %rdi
callq 0x2bde6
addq $0x848, %rsp            # imm = 0x848
popq %rbx
popq %r12
popq %r13
popq %r14
popq %r15
popq %rbp
retq
leaq 0x12b583(%rip), %rdi    # 0x14bf98
leaq 0x129921(%rip), %rsi    # 0x14a33d
leaq 0x12b58b(%rip), %rcx    # 0x14bfae
movl $0x76, %edx
callq 0xb200
jmp 0x20a4d
movq %rax, %rbx
movq 0x50(%rsp), %rax
testq %rax, %rax
je 0x20a58
leaq 0x40(%rsp), %rdi
movq %rdi, %rsi
movl $0x3, %edx
callq *%rax
jmp 0x20a58
movq %rax, %rdi
callq 0x171a3
movq %rax, %rbx
movq 0x28(%rsp), %rdi
testq %rdi, %rdi
je 0x20a88
movq 0x38(%rsp), %rsi
subq %rdi, %rsi
callq 0xb2f0
jmp 0x20a88
jmp 0x20a7b
jmp 0x20a7b
jmp 0x20a7b
jmp 0x20a7b
jmp 0x20a7b
movq %rax, %rbx
leaq 0x60(%rsp), %rdi
callq 0x2bde6
movq %rbx, %rdi
callq 0xb510