// File: /workspace/github_cpp_makefile_star2_O2/CMU-SAFARI[P]ramulator/src/Memory.h
// Function: ramulator::Memory<ramulator::DDR3, ramulator::Controller>::init_mapping_with_file(std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char>>)
void init_mapping_with_file(string filename){
        ifstream file(filename);
        assert(file.good() && "Bad mapping file");
        // possible line types are:
        // 0. Empty line
        // 1. Direct bit assignment   : component N   = x
        // 2. Direct range assignment : component N:M = x:y
        // 3. XOR bit assignment      : component N   = x y z ...
        // 4. Comment line            : # comment here
        string line;
        char delim[] = " \t";
        while (getline(file, line)) {
            short capture_flags = 0;
            int level = -1;
            int target_bit = -1, target_bit2 = -1;
            int source_bit = -1, source_bit2 = -1;
            // cout << "Processing: " << line << endl;
            bool is_range = false;
            while (true) { // process next word
                size_t start = line.find_first_not_of(delim);
                if (start == string::npos) // no more words
                    break;
                size_t end = line.find_first_of(delim, start);
                string word = line.substr(start, end - start);
                
                if (word.at(0) == '#')// starting a comment
                    break;
                
                size_t col_index;
                int source_min, target_min, target_max;
                switch (capture_flags){
                    case 0: // capturing the component name
                        // fetch component level from channel spec
                        for (int i = 0; i < int(T::Level::MAX); i++)
                            if (word.find(T::level_str[i]) != string::npos) {
                                level = i;
                                capture_flags ++;
                            }
                        break;

                    case 1: // capturing target bit(s)
                        col_index = word.find(":");
                        if ( col_index != string::npos ){
                            target_bit2 = stoi(word.substr(col_index+1));
                            word = word.substr(0,col_index);
                            is_range = true;
                        }
                        target_bit = stoi(word);
                        capture_flags ++;
                        break;

                    case 2: //this should be the delimiter
                        assert(word.find("=") != string::npos);
                        capture_flags ++;
                        break;

                    case 3:
                        if (is_range){
                            col_index = word.find(":");
                            source_bit  = stoi(word.substr(0,col_index));
                            source_bit2 = stoi(word.substr(col_index+1));
                            assert(source_bit2 - source_bit == target_bit2 - target_bit);
                            source_min = min(source_bit, source_bit2);
                            target_min = min(target_bit, target_bit2);
                            target_max = max(target_bit, target_bit2);
                            while (target_min <= target_max){
                                mapping_scheme[level][target_min].push_back(source_min);
                                // cout << target_min << " <- " << source_min << endl;
                                source_min ++;
                                target_min ++;
                            }
                        }
                        else {
                            source_bit = stoi(word);
                            mapping_scheme[level][target_bit].push_back(source_bit);
                        }
                }
                if (end == string::npos) { // this is the last word
                    break;
                }
                line = line.substr(end);
            }
        }
        if (dump_mapping)
            dump_mapping_scheme();
    }

// Assembly:
pushq %rbp
pushq %r15
pushq %r14
pushq %r13
pushq %r12
pushq %rbx
subq $0x298, %rsp            # imm = 0x298
movq %rdi, %r14
leaq 0x90(%rsp), %rbx
pushq $0x8
popq %rdx
movq %rbx, %rdi
callq 0xb450
movq (%rbx), %rax
movq -0x18(%rax), %rax
cmpl $0x0, 0xb0(%rsp,%rax)
jne 0x1d3c5
leaq 0x80(%rsp), %rax
movq %rax, -0x10(%rax)
andq $0x0, -0x8(%rax)
xorl %ecx, %ecx
movb %cl, (%rax)
leaq 0x14(%rsp), %r13
movb %cl, 0x2(%r13)
movw $0x920, (%r13)          # imm = 0x920
movq %r14, 0x40(%rsp)
leaq 0xb50(%r14), %rax
movq %rax, 0x18(%rsp)
leaq 0x70(%rsp), %r12
leaq 0x50(%rsp), %rbp
leaq 0x90(%rsp), %rdi
movq %r12, %rsi
callq 0xb0b0
movq (%rax), %rcx
movq -0x18(%rcx), %rcx
testb $0x5, 0x20(%rax,%rcx)
jne 0x1d34b
movl $0x0, (%rsp)
pushq $-0x1
popq %rbx
movl %ebx, 0x4(%rsp)
movl %ebx, 0x10(%rsp)
xorl %r15d, %r15d
movq %r12, %rdi
movq %r13, %rsi
xorl %edx, %edx
callq 0xb1e0
cmpq $-0x1, %rax
je 0x1d00a
movq %rax, %r14
movq %r12, %rdi
movq %r13, %rsi
movq %rax, %rdx
callq 0xb1a0
movq %r12, %rsi
movq %rax, 0x48(%rsp)
movq %rax, %rcx
subq %r14, %rcx
leaq 0x20(%rsp), %r13
movq %r13, %rdi
movq %r14, %rdx
callq 0xb2f0
movq %r13, %rdi
xorl %esi, %esi
callq 0xb520
cmpb $0x23, (%rax)
je 0x1d32b
cmpw $0x3, %r15w
ja 0x1d2fa
movzwl %r15w, %eax
leaq 0xb3fe4(%rip), %rcx     # 0xd1090
movslq (%rcx,%rax,4), %rax
addq %rcx, %rax
jmpq *%rax
leaq 0x119394(%rip), %r14    # 0x136450
xorl %r13d, %r13d
cmpq $0x5, %r13
je 0x1d2fa
leaq 0x20(%rsp), %rdi
movq %r14, %rsi
xorl %edx, %edx
callq 0xb550
xorl %ecx, %ecx
cmpq $-0x1, %rax
cmovnel %r13d, %ebx
setne %cl
addl %ecx, %r15d
incq %r13
addq $0x20, %r14
jmp 0x1d0bf
leaq 0x20(%rsp), %rdi
leaq 0xb422a(%rip), %rsi     # 0xd1327
xorl %edx, %edx
callq 0xb540
movw $0x3, %r15w
cmpq $-0x1, %rax
jne 0x1d2fa
jmp 0x1d387
testb $0x1, (%rsp)
je 0x1d298
leaq 0x20(%rsp), %r14
movq %r14, %rdi
leaq 0xb59ac(%rip), %rsi     # 0xd2add
xorl %edx, %edx
callq 0xb540
movq %rax, %r15
movq %rbp, %r13
movq %rbp, %rdi
movq %r14, %rsi
xorl %edx, %edx
movq %rax, %rcx
callq 0xb2f0
movq %r13, %rdi
xorl %esi, %esi
pushq $0xa
popq %rdx
callq 0x1e04b
movl %eax, %r14d
movq %r13, %rdi
callq 0xb568
incq %r15
movq %r13, %rdi
leaq 0x20(%rsp), %rsi
movq %r15, %rdx
pushq $-0x1
popq %rcx
callq 0xb2f0
movq %r13, %rdi
xorl %esi, %esi
pushq $0xa
popq %rdx
callq 0x1e04b
movl %eax, %r15d
movq %r13, %rdi
callq 0xb568
movl %r15d, %eax
subl %r14d, %eax
movl 0x10(%rsp), %r13d
movl %r13d, %ecx
movl 0x4(%rsp), %edx
subl %edx, %ecx
cmpl %ecx, %eax
jne 0x1d3a6
cmpl %r14d, %r15d
cmovll %r15d, %r14d
cmpl %edx, %r13d
movl %edx, %r15d
cmovll %r13d, %r15d
cmovll %edx, %r13d
cmpl %r13d, %r15d
jg 0x1d2f0
movl %ebx, 0x50(%rsp)
movq 0x18(%rsp), %rdi
movq %rbp, %rsi
callq 0x1e068
movl %r15d, 0xc(%rsp)
movq %rax, %rdi
leaq 0xc(%rsp), %rsi
callq 0x1e0b6
movl %r14d, 0x8(%rsp)
movq %rax, %rdi
leaq 0x8(%rsp), %rsi
callq 0x1e8c2
incl %r14d
incl %r15d
jmp 0x1d1c5
leaq 0x20(%rsp), %r15
movq %r15, %rdi
leaq 0xb58c3(%rip), %rsi     # 0xd2add
xorl %edx, %edx
callq 0xb540
cmpq $-0x1, %rax
je 0x1d280
movq %rax, %r14
leaq 0x1(%rax), %rdx
movq %rbp, %r13
movq %rbp, %rdi
movq %r15, %rsi
pushq $-0x1
popq %rcx
callq 0xb2f0
movq %r13, %rdi
xorl %esi, %esi
pushq $0xa
popq %rdx
callq 0x1e04b
movl %eax, 0x10(%rsp)
movq %r13, %rdi
callq 0xb568
movq %r13, %rdi
movq %r15, %rsi
xorl %edx, %edx
movq %r14, %rcx
callq 0xb2f0
movq %r15, %rdi
movq %r13, %rsi
callq 0xb340
movq %r13, %rdi
callq 0xb568
movb $0x1, %al
movl %eax, (%rsp)
movq %r15, %rdi
xorl %esi, %esi
pushq $0xa
popq %rdx
callq 0x1e04b
movl %eax, 0x4(%rsp)
movw $0x2, %r15w
jmp 0x1d2fa
leaq 0x20(%rsp), %rdi
xorl %esi, %esi
pushq $0xa
popq %rdx
callq 0x1e04b
movl %eax, %r14d
movl %ebx, 0x50(%rsp)
movq 0x18(%rsp), %rdi
movq %rbp, %rsi
callq 0x1e068
movl 0x4(%rsp), %ecx
movl %ecx, 0xc(%rsp)
movq %rax, %rdi
leaq 0xc(%rsp), %rsi
callq 0x1e0b6
movl %r14d, 0x8(%rsp)
movq %rax, %rdi
leaq 0x8(%rsp), %rsi
callq 0x1e8c2
movw $0x3, %r15w
movl $0x0, (%rsp)
jmp 0x1d2fa
movw $0x3, %r15w
movb $0x1, %al
movl %eax, (%rsp)
movq 0x48(%rsp), %rdx
cmpq $-0x1, %rdx
je 0x1d32b
movq %rbp, %rdi
movq %r12, %rsi
pushq $-0x1
popq %rcx
callq 0xb2f0
movq %r12, %rdi
movq %rbp, %rsi
callq 0xb340
movq %rbp, %rdi
callq 0xb568
movb $0x1, %r14b
jmp 0x1d32e
xorl %r14d, %r14d
leaq 0x20(%rsp), %rdi
callq 0xb568
testb %r14b, %r14b
leaq 0x14(%rsp), %r13
jne 0x1d041
jmp 0x1d00a
movq 0x40(%rsp), %rdi
cmpb $0x1, 0xc61(%rdi)
jne 0x1d35e
callq 0x1e104
leaq 0x70(%rsp), %rdi
callq 0xb568
leaq 0x90(%rsp), %rdi
callq 0xb0e0
addq $0x298, %rsp            # imm = 0x298
popq %rbx
popq %r12
popq %r13
popq %r14
popq %r15
popq %rbp
retq
leaq 0xb54a9(%rip), %rdi     # 0xd2837
leaq 0xb4e1c(%rip), %rsi     # 0xd21b1
leaq 0xb5419(%rip), %rcx     # 0xd27b5
movl $0x194, %edx            # imm = 0x194
callq 0xb210
leaq 0xb54a9(%rip), %rdi     # 0xd2856
leaq 0xb4dfd(%rip), %rsi     # 0xd21b1
leaq 0xb53fa(%rip), %rcx     # 0xd27b5
movl $0x19d, %edx            # imm = 0x19D
callq 0xb210
leaq 0xb53c7(%rip), %rdi     # 0xd2793
leaq 0xb4dde(%rip), %rsi     # 0xd21b1
leaq 0xb53db(%rip), %rcx     # 0xd27b5
movl $0x162, %edx            # imm = 0x162
callq 0xb210
jmp 0x1d40f
jmp 0x1d418
jmp 0x1d418
jmp 0x1d3f8
jmp 0x1d3f8
jmp 0x1d418
jmp 0x1d418
jmp 0x1d418
jmp 0x1d418
jmp 0x1d418
movq %rax, %rbx
leaq 0x50(%rsp), %rdi
callq 0xb568
jmp 0x1d41b
jmp 0x1d40f
jmp 0x1d418
jmp 0x1d418
jmp 0x1d418
movq %rax, %rbx
jmp 0x1d425
jmp 0x1d418
jmp 0x1d418
movq %rax, %rbx
leaq 0x20(%rsp), %rdi
callq 0xb568
leaq 0x70(%rsp), %rdi
callq 0xb568
leaq 0x90(%rsp), %rdi
callq 0xb0e0
movq %rbx, %rdi
callq 0xb4d0