// File: CMU-SAFARI[P]ramulator/src/DRAM.h
// Function: ramulator::DRAM<ramulator::DDR3>::update_timing(ramulator::DDR3::Command, int const*, long)
void DRAM<T>::update_timing(typename T::Command cmd, const int* addr, long clk)
{
    // I am not a target node: I am merely one of its siblings
    if (id != addr[int(level)]) {
        for (auto& t : timing[int(cmd)]) {
            if (!t.sibling)
                continue; // not an applicable timing parameter

            assert (t.dist == 1);

            long future = clk + t.val;
            next[int(t.cmd)] = max(next[int(t.cmd)], future); // update future
        }

        return; // stop recursion: only target nodes should be recursed
    }

    // I am a target node
    if (prev[int(cmd)].size()) {
        prev[int(cmd)].pop_back();  // FIXME TIANSHI why pop back?
        prev[int(cmd)].push_front(clk); // update history
    }

    for (auto& t : timing[int(cmd)]) {
        if (t.sibling)
            continue; // not an applicable timing parameter

        long past = prev[int(cmd)][t.dist-1];
        if (past < 0)
            continue; // not enough history

        long future = past + t.val;
        next[int(t.cmd)] = max(next[int(t.cmd)], future); // update future
        // TIANSHI: for refresh statistics
        if (spec->is_refreshing(cmd) && spec->is_opening(t.cmd)) {
          assert(past == clk);
          begin_of_refreshing = clk;
          end_of_refreshing = max(end_of_refreshing, next[int(t.cmd)]);
          refresh_cycles += end_of_refreshing - clk;
          if (cur_serving_requests > 0) {
            refresh_intervals.push_back(make_pair(begin_of_refreshing, end_of_refreshing));
          }
        }
    }

    // Some commands have timings that are higher that their scope levels, thus
    // we do not stop at the cmd's scope level
    if (!children.size())
        return; // stop recursion: updated all levels

    // recursively update *all* of my children
    for (auto child : children)
        child->update_timing(cmd, addr, clk);

}

// Assembly:
pushq %rbp
movq %rsp, %rbp
subq $0xc0, %rsp
movq %rdi, -0x8(%rbp)
movl %esi, -0xc(%rbp)
movq %rdx, -0x18(%rbp)
movq %rcx, -0x20(%rbp)
movq -0x8(%rbp), %rdx
movq %rdx, -0xb8(%rbp)
movl 0x39c(%rdx), %eax
movq -0x18(%rbp), %rcx
movslq 0x398(%rdx), %rdx
cmpl (%rcx,%rdx,4), %eax
je 0x45147
movq -0xb8(%rbp), %rax
movq 0x890(%rax), %rax
movslq -0xc(%rbp), %rcx
imulq $0x18, %rcx, %rcx
addq %rcx, %rax
movq %rax, -0x28(%rbp)
movq -0x28(%rbp), %rdi
callq 0x25fb0
movq %rax, -0x30(%rbp)
movq -0x28(%rbp), %rdi
callq 0x25fe0
movq %rax, -0x38(%rbp)
leaq -0x30(%rbp), %rdi
leaq -0x38(%rbp), %rsi
callq 0x26010
testb $0x1, %al
jne 0x4509c
jmp 0x45142
leaq -0x30(%rbp), %rdi
callq 0x26050
movq %rax, -0x40(%rbp)
movq -0x40(%rbp), %rax
testb $0x1, 0xc(%rax)
jne 0x450b5
jmp 0x45134
movq -0x40(%rbp), %rax
cmpl $0x1, 0x4(%rax)
jne 0x450c1
jmp 0x450e0
leaq 0x20c2f7(%rip), %rdi    # 0x2513bf
leaq 0x20c038(%rip), %rsi    # 0x251107
movl $0x168, %edx            # imm = 0x168
leaq 0x20c2f0(%rip), %rcx    # 0x2513cb
callq 0xc280
movq -0xb8(%rbp), %rdi
movq -0x20(%rbp), %rax
movq -0x40(%rbp), %rcx
movslq 0x8(%rcx), %rcx
addq %rcx, %rax
movq %rax, -0x48(%rbp)
addq $0x450, %rdi            # imm = 0x450
movq -0x40(%rbp), %rax
movslq (%rax), %rax
shlq $0x3, %rax
addq %rax, %rdi
leaq -0x48(%rbp), %rsi
callq 0x45510
movq %rax, %rcx
movq -0xb8(%rbp), %rax
movq (%rcx), %rdx
movq -0x40(%rbp), %rcx
movslq (%rcx), %rcx
movq %rdx, 0x450(%rax,%rcx,8)
leaq -0x30(%rbp), %rdi
callq 0x260b0
jmp 0x45086
jmp 0x4548d
movq -0xb8(%rbp), %rdi
addq $0x4b0, %rdi            # imm = 0x4B0
movslq -0xc(%rbp), %rax
imulq $0x50, %rax, %rax
addq %rax, %rdi
callq 0x28b30
cmpq $0x0, %rax
je 0x451ab
movq -0xb8(%rbp), %rdi
addq $0x4b0, %rdi            # imm = 0x4B0
movslq -0xc(%rbp), %rax
imulq $0x50, %rax, %rax
addq %rax, %rdi
callq 0x45550
movq -0xb8(%rbp), %rdi
addq $0x4b0, %rdi            # imm = 0x4B0
movslq -0xc(%rbp), %rax
imulq $0x50, %rax, %rax
addq %rax, %rdi
leaq -0x20(%rbp), %rsi
callq 0x455b0
movq -0xb8(%rbp), %rax
movq 0x890(%rax), %rax
movslq -0xc(%rbp), %rcx
imulq $0x18, %rcx, %rcx
addq %rcx, %rax
movq %rax, -0x50(%rbp)
movq -0x50(%rbp), %rdi
callq 0x25fb0
movq %rax, -0x58(%rbp)
movq -0x50(%rbp), %rdi
callq 0x25fe0
movq %rax, -0x60(%rbp)
leaq -0x58(%rbp), %rdi
leaq -0x60(%rbp), %rsi
callq 0x26010
testb $0x1, %al
jne 0x451f8
jmp 0x453e1
leaq -0x58(%rbp), %rdi
callq 0x26050
movq %rax, -0x68(%rbp)
movq -0x68(%rbp), %rax
testb $0x1, 0xc(%rax)
je 0x45214
jmp 0x453d3
movq -0xb8(%rbp), %rdi
addq $0x4b0, %rdi            # imm = 0x4B0
movslq -0xc(%rbp), %rax
imulq $0x50, %rax, %rax
addq %rax, %rdi
movq -0x68(%rbp), %rax
movl 0x4(%rax), %eax
subl $0x1, %eax
movslq %eax, %rsi
callq 0x45610
movq (%rax), %rax
movq %rax, -0x70(%rbp)
cmpq $0x0, -0x70(%rbp)
jge 0x45252
jmp 0x453d3
movq -0xb8(%rbp), %rdi
movq -0x70(%rbp), %rax
movq -0x68(%rbp), %rcx
movslq 0x8(%rcx), %rcx
addq %rcx, %rax
movq %rax, -0x78(%rbp)
addq $0x450, %rdi            # imm = 0x450
movq -0x68(%rbp), %rax
movslq (%rax), %rax
shlq $0x3, %rax
addq %rax, %rdi
leaq -0x78(%rbp), %rsi
callq 0x45510
movq %rax, %rcx
movq -0xb8(%rbp), %rax
movq (%rcx), %rdx
movq -0x68(%rbp), %rcx
movslq (%rcx), %rcx
movq %rdx, 0x450(%rax,%rcx,8)
movq 0x390(%rax), %rdi
movl -0xc(%rbp), %esi
callq 0x45640
testb $0x1, %al
jne 0x452be
jmp 0x453d1
movq -0xb8(%rbp), %rax
movq 0x390(%rax), %rdi
movq -0x68(%rbp), %rax
movl (%rax), %esi
callq 0x41c80
testb $0x1, %al
jne 0x452e0
jmp 0x453d1
movq -0x70(%rbp), %rax
cmpq -0x20(%rbp), %rax
jne 0x452ec
jmp 0x4530b
leaq 0x20c14b(%rip), %rdi    # 0x25143e
leaq 0x20be0d(%rip), %rsi    # 0x251107
movl $0x183, %edx            # imm = 0x183
leaq 0x20c0c5(%rip), %rcx    # 0x2513cb
callq 0xc280
movq -0xb8(%rbp), %rsi
movq -0x20(%rbp), %rax
movq %rax, 0x420(%rsi)
movq %rsi, %rdi
addq $0x428, %rdi            # imm = 0x428
addq $0x450, %rsi            # imm = 0x450
movq -0x68(%rbp), %rax
movslq (%rax), %rax
shlq $0x3, %rax
addq %rax, %rsi
callq 0x45510
movq -0xb8(%rbp), %rdi
movq (%rax), %rax
movq %rax, 0x428(%rdi)
movq 0x428(%rdi), %rax
subq -0x20(%rbp), %rax
movq %rax, -0x80(%rbp)
addq $0x98, %rdi
leaq -0x80(%rbp), %rsi
callq 0x40b80
movq -0xb8(%rbp), %rax
cmpl $0x0, 0x400(%rax)
jle 0x453cf
movq -0xb8(%rbp), %rsi
movq %rsi, %rax
addq $0x430, %rax            # imm = 0x430
movq %rax, -0xc0(%rbp)
movq %rsi, %rdi
addq $0x420, %rdi            # imm = 0x420
addq $0x428, %rsi            # imm = 0x428
callq 0x456a0
movq -0xc0(%rbp), %rdi
movq %rax, -0x90(%rbp)
movq %rdx, -0x88(%rbp)
leaq -0x90(%rbp), %rsi
callq 0x45670
jmp 0x453d1
jmp 0x453d3
leaq -0x58(%rbp), %rdi
callq 0x260b0
jmp 0x451e2
movq -0xb8(%rbp), %rdi
addq $0x3b0, %rdi            # imm = 0x3B0
callq 0x2bfd0
cmpq $0x0, %rax
jne 0x453ff
jmp 0x4548d
movq -0xb8(%rbp), %rax
addq $0x3b0, %rax            # imm = 0x3B0
movq %rax, -0x98(%rbp)
movq -0x98(%rbp), %rdi
callq 0x2be80
movq %rax, -0xa0(%rbp)
movq -0x98(%rbp), %rdi
callq 0x2bd10
movq %rax, -0xa8(%rbp)
leaq -0xa0(%rbp), %rdi
leaq -0xa8(%rbp), %rsi
callq 0x2ce10
testb $0x1, %al
jne 0x45452
jmp 0x4548d
leaq -0xa0(%rbp), %rdi
callq 0x2ce50
movq (%rax), %rax
movq %rax, -0xb0(%rbp)
movq -0xb0(%rbp), %rdi
movl -0xc(%rbp), %esi
movq -0x18(%rbp), %rdx
movq -0x20(%rbp), %rcx
callq 0x45010
leaq -0xa0(%rbp), %rdi
callq 0x2ce70
jmp 0x45439
addq $0xc0, %rsp
popq %rbp
retq
nopw %cs:(%rax,%rax)