// File: /workspace/github_cpp_makefile_star2_O3/CMU-SAFARI[P]MQSim/src/ssd/Address_Mapping_Unit_Page_Level.cpp
// Function: SSD_Components::Address_Mapping_Unit_Page_Level::Address_Mapping_Unit_Page_Level(std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char>> const&, SSD_Components::FTL*, SSD_Components::NVM_PHY_ONFI*, SSD_Components::Flash_Block_Manager_Base*, bool, unsigned int, SSD_Components::Flash_Plane_Allocation_Scheme_Type, unsigned int, unsigned int, unsigned int, unsigned int, unsigned int, std::vector<std::vector<unsigned int, std::allocator<unsigned int>>, std::allocator<std::vector<unsigned int, std::allocator<unsigned int>>>>, std::vector<std::vector<unsigned int, std::allocator<unsigned int>>, std::allocator<std::vector<unsigned int, std::allocator<unsigned int>>>>, std::vector<std::vector<unsigned int, std::allocator<unsigned int>>, std::allocator<std::vector<unsigned int, std::allocator<unsigned int>>>>, std::vector<std::vector<unsigned int, std::allocator<unsigned int>>, std::allocator<std::vector<unsigned int, std::allocator<unsigned int>>>>, unsigned int, unsigned int, unsigned int, unsigned int, double, SSD_Components::CMT_Sharing_Mode, bool)
Address_Mapping_Unit_Page_Level::Address_Mapping_Unit_Page_Level(const sim_object_id_type& id, FTL* ftl, NVM_PHY_ONFI* flash_controller, Flash_Block_Manager_Base* block_manager,
		bool ideal_mapping_table, unsigned int cmt_capacity_in_byte, Flash_Plane_Allocation_Scheme_Type PlaneAllocationScheme,
		unsigned int concurrent_stream_no,
		unsigned int channel_count, unsigned int chip_no_per_channel, unsigned int die_no_per_chip, unsigned int plane_no_per_die,
		std::vector<std::vector<flash_channel_ID_type>> stream_channel_ids, std::vector<std::vector<flash_chip_ID_type>> stream_chip_ids,
		std::vector<std::vector<flash_die_ID_type>> stream_die_ids, std::vector<std::vector<flash_plane_ID_type>> stream_plane_ids,
		unsigned int Block_no_per_plane, unsigned int Page_no_per_block, unsigned int SectorsPerPage, unsigned int PageSizeInByte,
		double Overprovisioning_ratio, CMT_Sharing_Mode sharing_mode, bool fold_large_addresses)
		: Address_Mapping_Unit_Base(id, ftl, flash_controller, block_manager, ideal_mapping_table,
			concurrent_stream_no, channel_count, chip_no_per_channel, die_no_per_chip, plane_no_per_die,
			Block_no_per_plane, Page_no_per_block, SectorsPerPage, PageSizeInByte, Overprovisioning_ratio, sharing_mode, fold_large_addresses)
	{
		_my_instance = this;
		domains = new AddressMappingDomain*[no_of_input_streams];

		Write_transactions_for_overfull_planes = new std::set<NVM_Transaction_Flash_WR*>***[channel_count];
		for (unsigned int channel_id = 0; channel_id < channel_count; channel_id++) {
			Write_transactions_for_overfull_planes[channel_id] = new std::set<NVM_Transaction_Flash_WR*>**[chip_no_per_channel];
			for (unsigned int chip_id = 0; chip_id < chip_no_per_channel; chip_id++) {
				Write_transactions_for_overfull_planes[channel_id][chip_id] = new std::set<NVM_Transaction_Flash_WR*>*[die_no_per_chip];
				for (unsigned int die_id = 0; die_id < die_no_per_chip; die_id++) {
					Write_transactions_for_overfull_planes[channel_id][chip_id][die_id] = new std::set<NVM_Transaction_Flash_WR*>[plane_no_per_die];
				}
			}
		}

		flash_channel_ID_type* channel_ids = NULL;
		flash_channel_ID_type* chip_ids = NULL;
		flash_channel_ID_type* die_ids = NULL;
		flash_channel_ID_type* plane_ids = NULL;
		for (unsigned int domainID = 0; domainID < no_of_input_streams; domainID++) {
			/* Since we want to have the same mapping table entry size for all streams, the entry size
			*  is calculated at this level and then pass it to the constructors of mapping domains
			* entry size = sizeOf(lpa) + sizeOf(ppn) + sizeOf(bit vector that shows written sectors of a page)
			*/
			CMT_entry_size = (unsigned int)std::ceil(((2 * std::log2(total_physical_pages_no)) + sector_no_per_page) / 8);
			//In GTD we do not need to store lpa
			GTD_entry_size = (unsigned int)std::ceil((std::log2(total_physical_pages_no) + sector_no_per_page) / 8);
			no_of_translation_entries_per_page = (SectorsPerPage * SECTOR_SIZE_IN_BYTE) / GTD_entry_size;

			Cached_Mapping_Table* sharedCMT = NULL;
			unsigned int per_stream_cmt_capacity = 0;
			cmt_capacity = cmt_capacity_in_byte / CMT_entry_size;
			switch (sharing_mode) {
				case CMT_Sharing_Mode::SHARED:
					per_stream_cmt_capacity = cmt_capacity;
					sharedCMT = new Cached_Mapping_Table(cmt_capacity);
					break;
				case CMT_Sharing_Mode::EQUAL_SIZE_PARTITIONING:
					per_stream_cmt_capacity = cmt_capacity / no_of_input_streams;
					break;
			}


			channel_ids = new flash_channel_ID_type[stream_channel_ids[domainID].size()];
			for (unsigned int i = 0; i < stream_channel_ids[domainID].size(); i++) {
				if (stream_channel_ids[domainID][i] < channel_count) {
					channel_ids[i] = stream_channel_ids[domainID][i];
				} else {
					PRINT_ERROR("Invalid channel ID specified for I/O flow " << domainID);
				}
			}

			chip_ids = new flash_channel_ID_type[stream_chip_ids[domainID].size()];
			for (unsigned int i = 0; i < stream_chip_ids[domainID].size(); i++) {
				if (stream_chip_ids[domainID][i] < chip_no_per_channel) {
					chip_ids[i] = stream_chip_ids[domainID][i];
				} else {
					PRINT_ERROR("Invalid chip ID specified for I/O flow " << domainID);
				}
			}

			die_ids = new flash_channel_ID_type[stream_die_ids[domainID].size()];
			for (unsigned int i = 0; i < stream_die_ids[domainID].size(); i++) {
				if (stream_die_ids[domainID][i] < die_no_per_chip) {
					die_ids[i] = stream_die_ids[domainID][i];
				} else {
					PRINT_ERROR("Invalid die ID specified for I/O flow " << domainID);
				}
			}

			plane_ids = new flash_channel_ID_type[stream_plane_ids[domainID].size()];
			for (unsigned int i = 0; i < stream_plane_ids[domainID].size(); i++) {
				if (stream_plane_ids[domainID][i] < plane_no_per_die) {
					plane_ids[i] = stream_plane_ids[domainID][i];
				} else {
					PRINT_ERROR("Invalid plane ID specified for I/O flow " << domainID);
				}
			}

			domains[domainID] = new AddressMappingDomain(per_stream_cmt_capacity, CMT_entry_size, no_of_translation_entries_per_page,
				sharedCMT,
				PlaneAllocationScheme,
				channel_ids, (unsigned int)(stream_channel_ids[domainID].size()), chip_ids, (unsigned int)(stream_chip_ids[domainID].size()), die_ids, 
				(unsigned int)(stream_die_ids[domainID].size()), plane_ids, (unsigned int)(stream_plane_ids[domainID].size()),
				Utils::Logical_Address_Partitioning_Unit::PDA_count_allocate_to_flow(domainID), Utils::Logical_Address_Partitioning_Unit::LHA_count_allocate_to_flow_from_device_view(domainID),
				sector_no_per_page);
			delete[] channel_ids;
			delete[] chip_ids;
			delete[] die_ids;
			delete[] plane_ids;
		}
	}

// Assembly:
pushq %rbp
pushq %r15
pushq %r14
pushq %r13
pushq %r12
pushq %rbx
subq $0x68, %rsp
movq %rdi, %r15
movl 0x118(%rsp), %r12d
movl 0x108(%rsp), %r13d
movl 0xd0(%rsp), %ebp
movl 0xc8(%rsp), %eax
movl 0xc0(%rsp), %r10d
movl 0xb8(%rsp), %ebx
movl 0x110(%rsp), %r11d
subq $0x8, %rsp
movzbl 0x128(%rsp), %r14d
pushq %r14
pushq %r12
pushq %r11
movq %r13, 0x60(%rsp)
pushq %r13
movl 0x128(%rsp), %r11d
pushq %r11
movl 0x128(%rsp), %r11d
pushq %r11
pushq %rbp
pushq %rax
pushq %r10
pushq %rbx
movl 0x108(%rsp), %eax
pushq %rax
callq 0x290d0
addq $0x60, %rsp
leaq 0x44171(%rip), %rax     # 0x6e0c8
movq %rax, (%r15)
movq %r15, 0x456a7(%rip)     # 0x6f608
movl 0x50(%r15), %eax
movq %rax, 0x50(%rsp)
leaq (,%rax,8), %rdi
movq %r15, 0x10(%rsp)
callq 0x7030
movq %rax, 0xa8(%r15)
movl %ebx, %eax
movq %rax, 0x20(%rsp)
leaq (,%rax,8), %rdi
callq 0x7030
movq %rax, 0xb8(%r15)
testl %ebx, %ebx
je 0x2a0db
movl 0xc0(%rsp), %eax
movl %eax, %eax
movq %rax, 0x28(%rsp)
leaq (,%rax,8), %rax
movq %rax, 0x18(%rsp)
movl 0xc8(%rsp), %eax
movl %eax, %eax
movq %rax, 0x8(%rsp)
leaq (,%rax,8), %rax
movq %rax, 0x30(%rsp)
movl 0xd0(%rsp), %eax
movl %eax, %ebp
movq %rbp, %rax
shlq $0x4, %rax
leaq (%rax,%rax,2), %rcx
movq %rcx, 0x38(%rsp)
leaq (%rax,%rax,2), %r12
addq $0x8, %r12
xorl %r14d, %r14d
xorl %ebx, %ebx
movq 0x18(%rsp), %rdi
callq 0x7030
movq 0x10(%rsp), %rcx
movq 0xb8(%rcx), %rcx
movq %rax, (%rcx,%rbx,8)
movl 0xc0(%rsp), %eax
testl %eax, %eax
je 0x2a0cd
xorl %r15d, %r15d
movq 0x30(%rsp), %rdi
callq 0x7030
movq 0x10(%rsp), %rcx
movq 0xb8(%rcx), %rcx
movq (%rcx,%rbx,8), %rcx
movq %rax, (%rcx,%r15,8)
movl 0xc8(%rsp), %eax
testl %eax, %eax
je 0x2a0bf
xorl %r13d, %r13d
movq %r12, %rdi
callq 0x7030
movq %rbp, (%rax)
movl 0xd0(%rsp), %ecx
testl %ecx, %ecx
je 0x2a099
leaq 0x10(%rax), %rcx
movq 0x38(%rsp), %rdx
movl $0x0, (%rcx)
movq %r14, 0x8(%rcx)
movq %rcx, 0x10(%rcx)
movq %rcx, 0x18(%rcx)
movq %r14, 0x20(%rcx)
addq $0x30, %rcx
addq $-0x30, %rdx
jne 0x2a079
addq $0x8, %rax
movq 0x10(%rsp), %rcx
movq 0xb8(%rcx), %rcx
movq (%rcx,%rbx,8), %rcx
movq (%rcx,%r15,8), %rcx
movq %rax, (%rcx,%r13,8)
incq %r13
cmpq 0x8(%rsp), %r13
jne 0x2a05a
incq %r15
cmpq 0x28(%rsp), %r15
jne 0x2a02e
incq %rbx
cmpq 0x20(%rsp), %rbx
jne 0x2a002
cmpl $0x0, 0x50(%rsp)
movq 0x10(%rsp), %r14
je 0x2a508
movq 0x40(%rsp), %rax
shll $0x9, %eax
movq %rax, 0x40(%rsp)
movq $0x0, 0x8(%rsp)
movq $-0x1, %r15
movl 0x84(%r14), %eax
cvtsi2sd %rax, %xmm0
callq 0x7630
movl 0x7c(%r14), %eax
cvtsi2sd %rax, %xmm1
movl 0x84(%r14), %ebx
addsd %xmm0, %xmm0
addsd %xmm1, %xmm0
movsd 0x2e24f(%rip), %xmm1    # 0x58388
mulsd %xmm1, %xmm0
callq 0x7090
cvttsd2si %xmm0, %rax
movl %eax, 0xb0(%r14)
xorps %xmm0, %xmm0
cvtsi2sd %rbx, %xmm0
callq 0x7630
movl 0x7c(%r14), %eax
movl 0xb0(%r14), %ebx
xorps %xmm1, %xmm1
cvtsi2sd %rax, %xmm1
addsd %xmm1, %xmm0
mulsd 0x2e20e(%rip), %xmm0    # 0x58388
callq 0x7090
cvttsd2si %xmm0, %rcx
movl %ecx, 0xb4(%r14)
movq 0x40(%rsp), %rax
xorl %edx, %edx
divl %ecx
movl %eax, 0x5c(%rsp)
movl %eax, 0xc0(%r14)
movl 0xa0(%rsp), %eax
xorl %edx, %edx
movl %ebx, 0x50(%rsp)
divl %ebx
movl %eax, %ecx
movl %eax, 0xa4(%r14)
movl 0x118(%rsp), %eax
cmpl $0x1, %eax
je 0x2a22b
testl %eax, %eax
movl 0xc0(%rsp), %r14d
jne 0x2a24e
movl %ecx, 0x20(%rsp)
movl $0x58, %edi
callq 0x73a0
movq %rax, 0x18(%rsp)
movq 0x18(%rsp), %rcx
leaq 0x30(%rcx), %rax
movq %rax, (%rcx)
movq $0x1, 0x8(%rcx)
xorpd %xmm0, %xmm0
movupd %xmm0, 0x10(%rcx)
movl $0x3f800000, 0x20(%rcx) # imm = 0x3F800000
movupd %xmm0, 0x28(%rcx)
movq %rcx, %rax
addq $0x38, %rax
movq %rax, 0x40(%rcx)
movq %rax, 0x38(%rcx)
movq $0x0, 0x48(%rcx)
movl 0x20(%rsp), %eax
movl %eax, 0x50(%rcx)
jmp 0x2a25f
movl %ecx, %eax
xorl %edx, %edx
movq 0x10(%rsp), %rcx
divl 0x50(%rcx)
movq $0x0, 0x18(%rsp)
movl %eax, 0x20(%rsp)
movl 0xc0(%rsp), %r14d
jmp 0x2a25f
movq $0x0, 0x18(%rsp)
movl $0x0, 0x20(%rsp)
movq 0xd8(%rsp), %rax
movq (%rax), %rbx
movq 0x8(%rsp), %rax
leaq (%rax,%rax,2), %r12
movq 0x8(%rbx,%r12,8), %rdi
subq (%rbx,%r12,8), %rdi
cmovsq %r15, %rdi
callq 0x7030
movq %rax, 0x38(%rsp)
leaq (%rbx,%r12,8), %rbp
movq (%rbp), %rax
movq 0x8(%rbp), %rcx
subq %rax, %rcx
movq 0x38(%rsp), %r9
movq %r12, %r10
je 0x2a2cf
sarq $0x2, %rcx
movl $0x1, %edx
xorl %esi, %esi
movl (%rax,%rsi,4), %edi
movl 0xb8(%rsp), %r8d
cmpl %r8d, %edi
jae 0x2a517
movl %edi, (%r9,%rsi,4)
movl %edx, %esi
incl %edx
cmpq %rsi, %rcx
ja 0x2a2ae
movq 0xe0(%rsp), %rax
movq (%rax), %rbx
movq 0x8(%rbx,%r10,8), %rdi
subq (%rbx,%r10,8), %rdi
cmovsq %r15, %rdi
movq %r10, %r12
callq 0x7030
movq %rax, 0x30(%rsp)
leaq (%rbx,%r12,8), %rcx
movq (%rcx), %rax
movq %rcx, %r13
movq 0x8(%rcx), %rcx
subq %rax, %rcx
movq 0x30(%rsp), %r8
movq %r12, %r9
je 0x2a333
sarq $0x2, %rcx
movl $0x1, %edx
xorl %esi, %esi
movl (%rax,%rsi,4), %edi
cmpl %r14d, %edi
jae 0x2a571
movl %edi, (%r8,%rsi,4)
movl %edx, %esi
incl %edx
cmpq %rsi, %rcx
ja 0x2a31a
movq 0xe8(%rsp), %rax
movq (%rax), %rbx
movq 0x8(%rbx,%r9,8), %rdi
subq (%rbx,%r9,8), %rdi
cmovsq %r15, %rdi
movq %r9, %r14
callq 0x7030
movq %rax, %r12
leaq (%rbx,%r14,8), %r10
movq (%r10), %rax
movq 0x8(%r10), %rcx
subq %rax, %rcx
movq %r14, %r9
je 0x2a395
sarq $0x2, %rcx
movl $0x1, %edx
xorl %esi, %esi
movl (%rax,%rsi,4), %edi
movl 0xc8(%rsp), %r8d
cmpl %r8d, %edi
jae 0x2a5cb
movl %edi, (%r12,%rsi,4)
movl %edx, %esi
incl %edx
cmpq %rsi, %rcx
ja 0x2a374
movq %r10, 0x48(%rsp)
movq 0xf0(%rsp), %rax
movq (%rax), %rbx
movq 0x8(%rbx,%r9,8), %rdi
subq (%rbx,%r9,8), %rdi
cmovsq %r15, %rdi
movq %r9, %r14
callq 0x7030
movq %rax, %r15
leaq (%rbx,%r14,8), %r9
movq (%r9), %rax
movq 0x8(%r9), %rcx
subq %rax, %rcx
je 0x2a3f9
sarq $0x2, %rcx
movl $0x1, %edx
xorl %esi, %esi
movl (%rax,%rsi,4), %edi
movl 0xd0(%rsp), %r8d
cmpl %r8d, %edi
jae 0x2a622
movl %edi, (%r15,%rsi,4)
movl %edx, %esi
incl %edx
cmpq %rsi, %rcx
ja 0x2a3d8
movq %r9, 0x60(%rsp)
movl $0x270, %edi            # imm = 0x270
callq 0x73a0
movq %rax, 0x28(%rsp)
movq 0x8(%rbp), %r14
subq (%rbp), %r14
movq 0x8(%r13), %rbx
subq (%r13), %rbx
movq 0x48(%rsp), %rax
movq 0x8(%rax), %r13
subq (%rax), %r13
movq 0x60(%rsp), %rax
movq 0x8(%rax), %rbp
subq (%rax), %rbp
movzwl 0x8(%rsp), %edi
callq 0x5312c
movq %rax, 0x48(%rsp)
movzwl 0x8(%rsp), %edi
callq 0x530a8
shrq $0x2, %r14
shrq $0x2, %rbx
shrq $0x2, %r13
shrq $0x2, %rbp
movq 0x10(%rsp), %rcx
movl 0x7c(%rcx), %r10d
subq $0x8, %rsp
movq 0x30(%rsp), %rdi
movl 0x28(%rsp), %esi
movl 0x58(%rsp), %edx
movl 0x64(%rsp), %ecx
movq 0x20(%rsp), %r8
movl 0xb0(%rsp), %r9d
pushq %r10
pushq %rax
pushq 0x60(%rsp)
pushq %rbp
pushq %r15
pushq %r13
pushq %r12
pushq %rbx
pushq 0x78(%rsp)
pushq %r14
pushq 0x90(%rsp)
callq 0x298ae
addq $0x60, %rsp
movq 0x10(%rsp), %r14
movq 0xa8(%r14), %rax
movq 0x8(%rsp), %rbx
movq 0x28(%rsp), %rcx
movq %rcx, (%rax,%rbx,8)
movq 0x38(%rsp), %rdi
callq 0x7480
movq 0x30(%rsp), %rdi
callq 0x7480
movq %r12, %rdi
callq 0x7480
movq %r15, %rdi
callq 0x7480
incq %rbx
movl 0x50(%r14), %eax
movq %rbx, 0x8(%rsp)
cmpq %rax, %rbx
movq $-0x1, %r15
jb 0x2a108
addq $0x68, %rsp
popq %rbx
popq %r12
popq %r13
popq %r14
popq %r15
popq %rbp
retq
movq 0x44ad2(%rip), %rdi     # 0x6eff0
leaq 0x2c083(%rip), %rsi     # 0x565a8
movl $0x6, %edx
callq 0x7400
movq 0x44aba(%rip), %rdi     # 0x6eff0
leaq 0x2e2ae(%rip), %rsi     # 0x587eb
movl $0x2a, %edx
callq 0x7400
movq 0x44aa2(%rip), %rdi     # 0x6eff0
movq 0x8(%rsp), %rsi
callq 0x7280
movq %rax, %rdi
callq 0x71c0
movq 0x44a69(%rip), %rdi     # 0x6efd0
callq 0x7430
jmp 0x2a677
movq 0x44a78(%rip), %rdi     # 0x6eff0
leaq 0x2c029(%rip), %rsi     # 0x565a8
movl $0x6, %edx
callq 0x7400
movq 0x44a60(%rip), %rdi     # 0x6eff0
leaq 0x2e27f(%rip), %rsi     # 0x58816
movl $0x27, %edx
callq 0x7400
movq 0x44a48(%rip), %rdi     # 0x6eff0
movq 0x8(%rsp), %rsi
callq 0x7280
movq %rax, %rdi
callq 0x71c0
movq 0x44a0f(%rip), %rdi     # 0x6efd0
callq 0x7430
jmp 0x2a677
movq 0x44a1e(%rip), %rdi     # 0x6eff0
leaq 0x2bfcf(%rip), %rsi     # 0x565a8
movl $0x6, %edx
callq 0x7400
movq 0x44a06(%rip), %rdi     # 0x6eff0
leaq 0x2e24d(%rip), %rsi     # 0x5883e
movl $0x26, %edx
callq 0x7400
movq 0x449ee(%rip), %rdi     # 0x6eff0
movq 0x8(%rsp), %rsi
callq 0x7280
movq %rax, %rdi
callq 0x71c0
movq 0x449b5(%rip), %rdi     # 0x6efd0
callq 0x7430
jmp 0x2a677
movq 0x449c7(%rip), %rdi     # 0x6eff0
leaq 0x2bf78(%rip), %rsi     # 0x565a8
movl $0x6, %edx
callq 0x7400
movq 0x449af(%rip), %rdi     # 0x6eff0
leaq 0x2e21d(%rip), %rsi     # 0x58865
movl $0x28, %edx
callq 0x7400
movq 0x44997(%rip), %rdi     # 0x6eff0
movq 0x8(%rsp), %rsi
callq 0x7280
movq %rax, %rdi
callq 0x71c0
movq 0x4495e(%rip), %rdi     # 0x6efd0
callq 0x7430
movl $0x1, %edi
callq 0x7440
jmp 0x2a6a0
jmp 0x2a6a0
movq %rax, %r15
movq 0x28(%rsp), %rdi
callq 0x7370
jmp 0x2a6a3
jmp 0x2a6a0
jmp 0x2a6a0
jmp 0x2a6a0
jmp 0x2a6a0
jmp 0x2a6a0
jmp 0x2a6a0
movq %rax, %r15
movq 0x10(%rsp), %rdi
callq 0x291f2
movq %r15, %rdi
callq 0x7620
nop