// File: CMU-SAFARI[P]ramulator/src/LPDDR4.cpp
// Function: ramulator::LPDDR4::init_speed()
void LPDDR4::init_speed()
{
    // 12Gb/16Gb RFCab/RFCpb TBD
    // Numbers are in DRAM cycles
    const static int RFCPB_TABLE[int(Org::MAX)][int(Speed::MAX)] = {
        {48,  72,  96},
        {72, 108, 144},
        {72, 108, 144}
    };

    const static int RFCAB_TABLE[int(Org::MAX)][int(Speed::MAX)] = {
        {104, 156, 208},
        {144, 216, 288},
        {144, 216, 288}
    };

    const static int REFI_TABLE[int(RefreshMode::MAX)][int(Speed::MAX)] = {
        {3124, 4685, 6247},
        {1563, 2344, 3125},
        { 782, 1172, 1563}
    };

    const static int XSR_TABLE[int(Org::MAX)][int(Speed::MAX)] = {
        {110, 165, 220},
        {150, 225, 300},
        {150, 225, 300},
    };

    int speed = 0, density = 0;
    switch (speed_entry.rate) {
        case 1600: speed = 0; break;
        case 2400: speed = 1; break;
        case 3200: speed = 2; break;
        default: assert(false);
    };
    switch (org_entry.size >> 10){
        case 2: density = 0; break;
        case 3: density = 1; break;
        case 4: density = 2; break;
        default: assert(false && "12Gb/16Gb is still TBD");
    }
    speed_entry.nRFCpb = RFCPB_TABLE[density][speed];
    speed_entry.nRFCab = RFCAB_TABLE[density][speed];
    speed_entry.nREFI = REFI_TABLE[int(refresh_mode)][speed];
    speed_entry.nXSR = XSR_TABLE[density][speed];
}

// Assembly:
pushq %rbp
movq %rsp, %rbp
subq $0x30, %rsp
movq %rdi, -0x8(%rbp)
movq -0x8(%rbp), %rax
movq %rax, -0x20(%rbp)
movl $0x0, -0xc(%rbp)
movl $0x0, -0x10(%rbp)
movl 0x2a80(%rax), %eax
movl %eax, -0x14(%rbp)
subl $0x640, %eax            # imm = 0x640
je 0x1dc6dc
jmp 0x1dc6c4
movl -0x14(%rbp), %eax
subl $0x960, %eax            # imm = 0x960
je 0x1dc6e5
jmp 0x1dc6d0
movl -0x14(%rbp), %eax
subl $0xc80, %eax            # imm = 0xC80
je 0x1dc6ee
jmp 0x1dc6f7
movl $0x0, -0xc(%rbp)
jmp 0x1dc716
movl $0x1, -0xc(%rbp)
jmp 0x1dc716
movl $0x2, -0xc(%rbp)
jmp 0x1dc716
leaq 0x73463(%rip), %rdi     # 0x24fb61
leaq 0x837fb(%rip), %rsi     # 0x25ff00
movl $0x56, %edx
leaq 0x837fe(%rip), %rcx     # 0x25ff0f
callq 0xc280
movq -0x20(%rbp), %rax
movl 0x28ec(%rax), %eax
sarl $0xa, %eax
movl %eax, -0x24(%rbp)
subl $0x2, %eax
je 0x1dc741
jmp 0x1dc72d
movl -0x24(%rbp), %eax
subl $0x3, %eax
je 0x1dc74a
jmp 0x1dc737
movl -0x24(%rbp), %eax
subl $0x4, %eax
je 0x1dc753
jmp 0x1dc75c
movl $0x0, -0x10(%rbp)
jmp 0x1dc77b
movl $0x1, -0x10(%rbp)
jmp 0x1dc77b
movl $0x2, -0x10(%rbp)
jmp 0x1dc77b
leaq 0x82eb0(%rip), %rdi     # 0x25f613
leaq 0x83796(%rip), %rsi     # 0x25ff00
movl $0x5c, %edx
leaq 0x83799(%rip), %rcx     # 0x25ff0f
callq 0xc280
movq -0x20(%rbp), %rax
movslq -0x10(%rbp), %rdx
leaq 0x83376(%rip), %rcx     # 0x25fb00
imulq $0xc, %rdx, %rdx
addq %rdx, %rcx
movslq -0xc(%rbp), %rdx
movl (%rcx,%rdx,4), %ecx
movl %ecx, 0x2ae0(%rax)
movslq -0x10(%rbp), %rdx
leaq 0x83387(%rip), %rcx     # 0x25fb30
imulq $0xc, %rdx, %rdx
addq %rdx, %rcx
movslq -0xc(%rbp), %rdx
movl (%rcx,%rdx,4), %ecx
movl %ecx, 0x2adc(%rax)
movslq 0x2908(%rax), %rdx
leaq 0x83395(%rip), %rcx     # 0x25fb60
imulq $0xc, %rdx, %rdx
addq %rdx, %rcx
movslq -0xc(%rbp), %rdx
movl (%rcx,%rdx,4), %ecx
movl %ecx, 0x2ae4(%rax)
movslq -0x10(%rbp), %rdx
leaq 0x833a6(%rip), %rcx     # 0x25fb90
imulq $0xc, %rdx, %rdx
addq %rdx, %rcx
movslq -0xc(%rbp), %rdx
movl (%rcx,%rdx,4), %ecx
movl %ecx, 0x2af4(%rax)
addq $0x30, %rsp
popq %rbp
retq
nopw %cs:(%rax,%rax)