// File: CMU-SAFARI[P]ramulator/src/Main.cpp
// Function: void run_dramtrace<ramulator::DDR3>(ramulator::Config const&, ramulator::Memory<ramulator::DDR3, ramulator::Controller>&, char const*)
void run_dramtrace(const Config& configs, Memory<T, Controller>& memory, const char* tracename) {

    /* initialize DRAM trace */
    Trace trace(tracename);

    /* run simulation */
    bool stall = false, end = false;
    int reads = 0, writes = 0, clks = 0;
    long addr = 0;
    Request::Type type = Request::Type::READ;
    map<int, int> latencies;
    auto read_complete = [&latencies](Request& r){latencies[r.depart - r.arrive]++;};

    Request req(addr, type, read_complete);

    while (!end || memory.pending_requests()){
        if (!end && !stall){
            end = !trace.get_dramtrace_request(addr, type);
        }

        if (!end){
            req.addr = addr;
            req.type = type;
            stall = !memory.send(req);
            if (!stall){
                if (type == Request::Type::READ) reads++;
                else if (type == Request::Type::WRITE) writes++;
            }
        }
        else {
            memory.set_high_writeq_watermark(0.0f); // make sure that all write requests in the
                                                    // write queue are drained
        }

        memory.tick();
        clks ++;
        Stats::curTick++; // memory clock, global, for Statistics
    }
    // This a workaround for statistics set only initially lost in the end
    memory.finish();
    Stats::statlist.printall();

}

// Assembly:
pushq %rbp
movq %rsp, %rbp
subq $0x3d0, %rsp            # imm = 0x3D0
movq %rdi, -0x8(%rbp)
movq %rsi, -0x10(%rbp)
movq %rdx, -0x18(%rbp)
movq -0x18(%rbp), %rsi
leaq -0x248(%rbp), %rdi
callq 0x1f9f10
movb $0x0, -0x249(%rbp)
movb $0x0, -0x24a(%rbp)
movl $0x0, -0x250(%rbp)
movl $0x0, -0x254(%rbp)
movl $0x0, -0x258(%rbp)
movq $0x0, -0x260(%rbp)
movl $0x0, -0x264(%rbp)
leaq -0x298(%rbp), %rdi
movq %rdi, -0x3b0(%rbp)
callq 0x4c9f0
movq -0x3b0(%rbp), %rax
movq %rax, -0x2a0(%rbp)
movq -0x260(%rbp), %rax
movq %rax, -0x3a8(%rbp)
movl -0x264(%rbp), %eax
movl %eax, -0x39c(%rbp)
leaq -0x320(%rbp), %rdi
movq %rdi, -0x398(%rbp)
leaq -0x2a0(%rbp), %rsi
callq 0x4ca10
movq -0x3a8(%rbp), %rsi
movl -0x39c(%rbp), %edx
movq -0x398(%rbp), %rcx
leaq -0x300(%rbp), %rdi
xorl %r8d, %r8d
callq 0x4caa0
jmp 0x25882
leaq -0x320(%rbp), %rdi
callq 0x367b0
movb $0x1, %al
testb $0x1, -0x24a(%rbp)
movb %al, -0x3b1(%rbp)
je 0x258c6
movq -0x10(%rbp), %rdi
movq (%rdi), %rax
movq 0x28(%rax), %rax
callq *%rax
movl %eax, -0x3b8(%rbp)
jmp 0x258b4
movl -0x3b8(%rbp), %eax
cmpl $0x0, %eax
setne %al
movb %al, -0x3b1(%rbp)
movb -0x3b1(%rbp), %al
testb $0x1, %al
jne 0x258d5
jmp 0x25a8a
testb $0x1, -0x24a(%rbp)
jne 0x25955
testb $0x1, -0x249(%rbp)
jne 0x25955
leaq -0x248(%rbp), %rdi
leaq -0x260(%rbp), %rsi
leaq -0x264(%rbp), %rdx
callq 0x1fa040
movb %al, -0x3b9(%rbp)
jmp 0x25909
movb -0x3b9(%rbp), %al
xorb $-0x1, %al
andb $0x1, %al
movb %al, -0x24a(%rbp)
jmp 0x25955
movq %rax, %rcx
movl %edx, %eax
movq %rcx, -0x328(%rbp)
movl %eax, -0x32c(%rbp)
leaq -0x320(%rbp), %rdi
callq 0x367b0
jmp 0x25ae0
movq %rax, %rcx
movl %edx, %eax
movq %rcx, -0x328(%rbp)
movl %eax, -0x32c(%rbp)
jmp 0x25ad4
testb $0x1, -0x24a(%rbp)
jne 0x25a3b
movq -0x260(%rbp), %rax
movq %rax, -0x2f8(%rbp)
movl -0x264(%rbp), %eax
movl %eax, -0x2d4(%rbp)
movq -0x10(%rbp), %rax
movq %rax, -0x3c8(%rbp)
leaq -0x390(%rbp), %rdi
leaq -0x300(%rbp), %rsi
callq 0x42ba0
jmp 0x2599c
movq -0x3c8(%rbp), %rdi
movq (%rdi), %rax
movq 0x20(%rax), %rax
leaq -0x390(%rbp), %rsi
callq *%rax
movb %al, -0x3c9(%rbp)
jmp 0x259bb
movb -0x3c9(%rbp), %al
xorb $-0x1, %al
andb $0x1, %al
movb %al, -0x249(%rbp)
leaq -0x390(%rbp), %rdi
callq 0x36780
testb $0x1, -0x249(%rbp)
jne 0x25a39
cmpl $0x0, -0x264(%rbp)
jne 0x25a1d
movl -0x250(%rbp), %eax
addl $0x1, %eax
movl %eax, -0x250(%rbp)
jmp 0x25a37
movq %rax, %rcx
movl %edx, %eax
movq %rcx, -0x328(%rbp)
movl %eax, -0x32c(%rbp)
leaq -0x390(%rbp), %rdi
callq 0x36780
jmp 0x25ad4
cmpl $0x1, -0x264(%rbp)
jne 0x25a35
movl -0x254(%rbp), %eax
addl $0x1, %eax
movl %eax, -0x254(%rbp)
jmp 0x25a37
jmp 0x25a39
jmp 0x25a4f
movq -0x10(%rbp), %rdi
movq (%rdi), %rax
movq 0x48(%rax), %rax
xorps %xmm0, %xmm0
callq *%rax
jmp 0x25a4d
jmp 0x25a4f
movq -0x10(%rbp), %rdi
movq (%rdi), %rax
movq 0x18(%rax), %rax
callq *%rax
jmp 0x25a5e
movl -0x258(%rbp), %eax
addl $0x1, %eax
movl %eax, -0x258(%rbp)
leaq 0x329924(%rip), %rax    # 0x34f398
movq (%rax), %rcx
addq $0x1, %rcx
leaq 0x329916(%rip), %rax    # 0x34f398
movq %rcx, (%rax)
jmp 0x2588e
movq -0x10(%rbp), %rdi
movq (%rdi), %rax
movq 0x30(%rax), %rax
callq *%rax
jmp 0x25a99
leaq 0x3296e0(%rip), %rdi    # 0x34f180
callq 0x4a1e0
jmp 0x25aa7
leaq -0x300(%rbp), %rdi
callq 0x36780
leaq -0x298(%rbp), %rdi
callq 0x4cb40
leaq -0x248(%rbp), %rdi
callq 0x4c200
addq $0x3d0, %rsp            # imm = 0x3D0
popq %rbp
retq
leaq -0x300(%rbp), %rdi
callq 0x36780
leaq -0x298(%rbp), %rdi
callq 0x4cb40
leaq -0x248(%rbp), %rdi
callq 0x4c200
movq -0x328(%rbp), %rdi
callq 0xc5d0
nopw %cs:(%rax,%rax)
nop