// File: CMU-SAFARI[P]ramulator/src/Memory.h
// Function: ramulator::Memory<ramulator::DDR3, ramulator::Controller>::send(ramulator::Request)
bool send(Request req)
    {
        req.addr_vec.resize(addr_bits.size());
        long addr = req.addr;
        int coreid = req.coreid;

        // Each transaction size is 2^tx_bits, so first clear the lowest tx_bits bits
        clear_lower_bits(addr, tx_bits);

        if (use_mapping_file){
            apply_mapping(addr, req.addr_vec);
        }
        else {
            switch(int(type)){
                case int(Type::ChRaBaRoCo):
                    for (int i = addr_bits.size() - 1; i >= 0; i--)
                        req.addr_vec[i] = slice_lower_bits(addr, addr_bits[i]);
                    break;
                case int(Type::RoBaRaCoCh):
                    req.addr_vec[0] = slice_lower_bits(addr, addr_bits[0]);
                    req.addr_vec[addr_bits.size() - 1] = slice_lower_bits(addr, addr_bits[addr_bits.size() - 1]);
                    for (int i = 1; i <= int(T::Level::Row); i++)
                        req.addr_vec[i] = slice_lower_bits(addr, addr_bits[i]);
                    break;
                default:
                    assert(false);
            }
        }

        if(ctrls[req.addr_vec[0]]->enqueue(req)) {
            // tally stats here to avoid double counting for requests that aren't enqueued
            ++num_incoming_requests;
            if (req.type == Request::Type::READ) {
              ++num_read_requests[coreid];
              ++incoming_read_reqs_per_channel[req.addr_vec[int(T::Level::Channel)]];
            }
            if (req.type == Request::Type::WRITE) {
              ++num_write_requests[coreid];
            }
            ++incoming_requests_per_channel[req.addr_vec[int(T::Level::Channel)]];
            return true;
        }

        return false;
    }

// Assembly:
pushq %rbp
movq %rsp, %rbp
subq $0x90, %rsp
movq %rsi, -0x40(%rbp)
movq %rdi, -0x10(%rbp)
movq %rsi, -0x18(%rbp)
movq -0x10(%rbp), %rdi
movq %rdi, -0x38(%rbp)
addq $0x10, %rsi
movq %rsi, -0x48(%rbp)
addq $0xc28, %rdi            # imm = 0xC28
callq 0x31ca0
movq -0x48(%rbp), %rdi
movq %rax, %rsi
callq 0x47680
movq -0x40(%rbp), %rsi
movq -0x38(%rbp), %rdi
movq 0x8(%rsi), %rax
movq %rax, -0x20(%rbp)
movl 0x28(%rsi), %eax
movl %eax, -0x24(%rbp)
movl 0xc64(%rdi), %edx
leaq -0x20(%rbp), %rsi
callq 0x47710
movq -0x38(%rbp), %rax
testb $0x1, 0xc60(%rax)
je 0x38a2b
movq -0x38(%rbp), %rdi
movq -0x40(%rbp), %rdx
movq -0x20(%rbp), %rsi
addq $0x10, %rdx
callq 0x47740
jmp 0x38bd9
movq -0x38(%rbp), %rax
movl 0xb80(%rax), %eax
movl %eax, -0x4c(%rbp)
testl %eax, %eax
je 0x38a4b
jmp 0x38a3e
movl -0x4c(%rbp), %eax
subl $0x1, %eax
je 0x38ab4
jmp 0x38bb8
movq -0x38(%rbp), %rdi
addq $0xc28, %rdi            # imm = 0xC28
callq 0x31ca0
subq $0x1, %rax
movl %eax, -0x28(%rbp)
cmpl $0x0, -0x28(%rbp)
jl 0x38aaf
movq -0x38(%rbp), %rdi
addq $0xc28, %rdi            # imm = 0xC28
movslq -0x28(%rbp), %rsi
callq 0x384f0
movq -0x38(%rbp), %rdi
movl (%rax), %edx
leaq -0x20(%rbp), %rsi
callq 0x47970
movq -0x40(%rbp), %rdi
movl %eax, -0x50(%rbp)
addq $0x10, %rdi
movslq -0x28(%rbp), %rsi
callq 0x384f0
movl -0x50(%rbp), %ecx
movl %ecx, (%rax)
movl -0x28(%rbp), %eax
addl $-0x1, %eax
movl %eax, -0x28(%rbp)
jmp 0x38a62
jmp 0x38bd7
movq -0x38(%rbp), %rdi
addq $0xc28, %rdi            # imm = 0xC28
xorl %eax, %eax
movl %eax, %esi
callq 0x384f0
movq -0x38(%rbp), %rdi
movl (%rax), %edx
leaq -0x20(%rbp), %rsi
callq 0x47970
movq -0x40(%rbp), %rdi
movl %eax, -0x6c(%rbp)
addq $0x10, %rdi
xorl %eax, %eax
movl %eax, %esi
callq 0x384f0
movl -0x6c(%rbp), %ecx
movq -0x38(%rbp), %rdi
movl %ecx, (%rax)
movq %rdi, %rax
addq $0xc28, %rax            # imm = 0xC28
movq %rax, -0x68(%rbp)
addq $0xc28, %rdi            # imm = 0xC28
callq 0x31ca0
movq -0x68(%rbp), %rdi
movq %rax, %rsi
subq $0x1, %rsi
callq 0x384f0
movq -0x38(%rbp), %rdi
movl (%rax), %edx
leaq -0x20(%rbp), %rsi
callq 0x47970
movq -0x38(%rbp), %rdi
movl %eax, %ecx
movq -0x40(%rbp), %rax
movl %ecx, -0x54(%rbp)
addq $0x10, %rax
movq %rax, -0x60(%rbp)
addq $0xc28, %rdi            # imm = 0xC28
callq 0x31ca0
movq -0x60(%rbp), %rdi
movq %rax, %rsi
subq $0x1, %rsi
callq 0x384f0
movl -0x54(%rbp), %ecx
movl %ecx, (%rax)
movl $0x1, -0x2c(%rbp)
cmpl $0x3, -0x2c(%rbp)
jg 0x38bb6
movq -0x38(%rbp), %rdi
addq $0xc28, %rdi            # imm = 0xC28
movslq -0x2c(%rbp), %rsi
callq 0x384f0
movq -0x38(%rbp), %rdi
movl (%rax), %edx
leaq -0x20(%rbp), %rsi
callq 0x47970
movq -0x40(%rbp), %rdi
movl %eax, -0x70(%rbp)
addq $0x10, %rdi
movslq -0x2c(%rbp), %rsi
callq 0x384f0
movl -0x70(%rbp), %ecx
movl %ecx, (%rax)
movl -0x2c(%rbp), %eax
addl $0x1, %eax
movl %eax, -0x2c(%rbp)
jmp 0x38b69
jmp 0x38bd7
leaq 0x216fa2(%rip), %rdi    # 0x24fb61
leaq 0x217df3(%rip), %rsi    # 0x2509b9
movl $0x14b, %edx            # imm = 0x14B
leaq 0x218a06(%rip), %rcx    # 0x2515d8
callq 0xc280
jmp 0x38bd9
movq -0x40(%rbp), %rdi
movq -0x38(%rbp), %rax
addq $0xc08, %rax            # imm = 0xC08
movq %rax, -0x78(%rbp)
addq $0x10, %rdi
xorl %eax, %eax
movl %eax, %esi
callq 0x384f0
movq -0x78(%rbp), %rdi
movslq (%rax), %rsi
callq 0x37b90
movq -0x40(%rbp), %rsi
movq (%rax), %rdi
callq 0x42730
testb $0x1, %al
jne 0x38c19
jmp 0x38ce3
movq -0x38(%rbp), %rdi
addq $0x138, %rdi            # imm = 0x138
callq 0x3fd50
movq -0x40(%rbp), %rax
cmpl $0x0, 0x2c(%rax)
jne 0x38c80
movq -0x38(%rbp), %rdi
addq $0x1d0, %rdi            # imm = 0x1D0
movl -0x24(%rbp), %esi
callq 0x41b70
movq %rax, %rdi
callq 0x40990
movq -0x38(%rbp), %rax
movq -0x40(%rbp), %rdi
addq $0x478, %rax            # imm = 0x478
movq %rax, -0x80(%rbp)
addq $0x10, %rdi
xorl %eax, %eax
movl %eax, %esi
callq 0x384f0
movq -0x80(%rbp), %rdi
movl (%rax), %esi
callq 0x41b70
movq %rax, %rdi
callq 0x40990
movq -0x40(%rbp), %rax
cmpl $0x1, 0x2c(%rax)
jne 0x38ca5
movq -0x38(%rbp), %rdi
addq $0x280, %rdi            # imm = 0x280
movl -0x24(%rbp), %esi
callq 0x41b70
movq %rax, %rdi
callq 0x40990
movq -0x40(%rbp), %rdi
movq -0x38(%rbp), %rax
addq $0x3c8, %rax            # imm = 0x3C8
movq %rax, -0x88(%rbp)
addq $0x10, %rdi
xorl %eax, %eax
movl %eax, %esi
callq 0x384f0
movq -0x88(%rbp), %rdi
movl (%rax), %esi
callq 0x41b70
movq %rax, %rdi
callq 0x40990
movb $0x1, -0x1(%rbp)
jmp 0x38ce7
movb $0x0, -0x1(%rbp)
movb -0x1(%rbp), %al
andb $0x1, %al
addq $0x90, %rsp
popq %rbp
retq
nopw %cs:(%rax,%rax)
nop