// File: /workspace/github_cpp_makefile_star2_O1/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, %rbp
movslq 0x3c(%rdi), %rax
movq %rax, 0x10(%rsp)
movl 0x40(%rdi), %eax
movl %eax, 0xc(%rsp)
leaq 0x28(%rsp), %rdi
movq %rdx, %rsi
callq 0x2b9d2
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 0xb457(%rip), %rax      # 0x2bc9e
movq %rax, 0x18(%rcx)
leaq 0xb45c(%rip), %rax      # 0x2bcae
movq %rax, 0x10(%rcx)
leaq 0x60(%rsp), %rdi
leaq 0x28(%rsp), %rdx
movq %rbp, %rsi
movq %rbx, %r8
callq 0x12ed7c
movq 0x50(%rsp), %rax
testq %rax, %rax
je 0x20884
leaq 0x40(%rsp), %rdi
movq %rdi, %rsi
movl $0x3, %edx
callq *%rax
movq 0x28(%rsp), %rdi
testq %rdi, %rdi
je 0x2089b
movq 0x38(%rsp), %rsi
subq %rdi, %rsi
callq 0xb2f0
movq 0x50(%rbp), %r14
testq %r14, %r14
je 0x2097a
movq 0x10(%rsp), %rax
decq %rax
movq %rax, 0x20(%rsp)
xorl %r15d, %r15d
movl $0x1, %r12d
movq %rbp, 0x18(%rsp)
leaq 0x60(%rsp), %rdi
callq 0x12f5b4
movl 0xc(%rsp), %ebp
testl %ebp, %ebp
setle %cl
leaq 0x184a1b(%rip), %rax    # 0x1a52f8
incq (%rax)
movq %r15, %rax
cqto
idivq 0x10(%rsp)
cmpq 0x20(%rsp), %rdx
setne %al
orb %cl, %al
jne 0x20903
movq (%rbx), %rax
movq %rbx, %rdi
callq *0x18(%rax)
decl %ebp
jne 0x208f6
movq 0x60(%rsp), %rax
cmpq %rax, 0x68(%rsp)
je 0x20943
xorl %ebp, %ebp
xorl %r13d, %r13d
movq (%rax,%rbp,8), %rdi
callq 0x12ff6c
cmpq %r14, %rax
movzbl %r13b, %r13d
cmovll %r12d, %r13d
incq %rbp
movq 0x60(%rsp), %rax
movq 0x68(%rsp), %rcx
subq %rax, %rcx
sarq $0x3, %rcx
cmpq %rbp, %rcx
ja 0x20914
jmp 0x20946
xorl %r13d, %r13d
testb $0x1, %r13b
movq 0x18(%rsp), %rbp
je 0x2095f
leaq 0x60(%rsp), %rdi
callq 0x12fef4
testb %al, %al
jne 0x2096e
incq %r15
testb $0x1, %r13b
jne 0x208c3
jmp 0x2097a
leaq 0x132da4(%rip), %rdi    # 0x153719
callq 0xb420
movb $0x1, 0x183951(%rip)    # 0x1a42d2
leaq 0x132e09(%rip), %rdi    # 0x153791
callq 0xb420
callq 0x13e93c
leaq 0x60(%rsp), %rdi
callq 0x12ff76
leaq 0x60(%rsp), %rdi
callq 0x12ff3a
testq %rax, %rax
jne 0x20a94
movl 0xc(%rsp), %r15d
movslq %r15d, %r14
leaq 0x132df7(%rip), %rdi    # 0x1537b5
callq 0xb420
movq 0x10(%rsp), %rax
imull %r15d, %eax
movslq %eax, %r12
xorl %r15d, %r15d
movq %r15, %rax
cqto
idivq %r12
movq %rdx, %r13
movq %rdx, %rax
cqto
idivq %r14
testq %rdx, %rdx
jne 0x20a2b
leaq 0x60(%rsp), %rdi
callq 0x12f5b4
leaq 0x1848fd(%rip), %rax    # 0x1a52f8
incq (%rax)
cmpq $0x0, 0x48(%rbp)
je 0x20a11
leaq 0x60(%rsp), %rdi
callq 0x12fef4
jmp 0x20a27
movq %rbp, %rdi
callq 0x2ba52
testb %al, %al
je 0x20a48
leaq 0x60(%rsp), %rdi
callq 0x12fce6
testb %al, %al
jne 0x20a63
movq %r13, %rax
cqto
idivq 0x10(%rsp)
testq %rdx, %rdx
jne 0x20a43
movq (%rbx), %rax
movq %rbx, %rdi
callq *0x18(%rax)
incq %r15
jmp 0x209d2
leaq 0x60(%rsp), %rdi
callq 0x12fce6
testb %al, %al
je 0x20a2b
movq (%rbx), %rax
movq %rbx, %rdi
callq *0x28(%rax)
testl %eax, %eax
jne 0x20a2b
movq (%rbx), %rax
movq %rbx, %rdi
callq *0x30(%rax)
leaq 0x18466d(%rip), %rdi    # 0x1a50e0
callq 0x2bb46
leaq 0x60(%rsp), %rdi
callq 0x2bbde
addq $0x848, %rsp            # imm = 0x848
popq %rbx
popq %r12
popq %r13
popq %r14
popq %r15
popq %rbp
retq
leaq 0x12e4bd(%rip), %rdi    # 0x14ef58
leaq 0x12c85b(%rip), %rsi    # 0x14d2fd
leaq 0x12e4c5(%rip), %rcx    # 0x14ef6e
movl $0x76, %edx
callq 0xb200
jmp 0x20ad3
movq %rax, %rbx
movq 0x50(%rsp), %rax
testq %rax, %rax
je 0x20ade
leaq 0x40(%rsp), %rdi
movq %rdi, %rsi
movl $0x3, %edx
callq *%rax
jmp 0x20ade
movq %rax, %rdi
callq 0x1718f
movq %rax, %rbx
movq 0x28(%rsp), %rdi
testq %rdi, %rdi
je 0x20b0e
movq 0x38(%rsp), %rsi
subq %rdi, %rsi
callq 0xb2f0
jmp 0x20b0e
jmp 0x20b01
jmp 0x20b01
jmp 0x20b01
jmp 0x20b01
jmp 0x20b01
movq %rax, %rbx
leaq 0x60(%rsp), %rdi
callq 0x2bbde
movq %rbx, %rdi
callq 0xb510