// File: /workspace/github_cpp_makefile_star2_O1/CMU-SAFARI[P]MQSim/src/ssd/Address_Mapping_Unit_Page_Level.cpp
// Function: SSD_Components::Address_Mapping_Unit_Page_Level::request_mapping_entry(unsigned short, unsigned long)
bool Address_Mapping_Unit_Page_Level::request_mapping_entry(const stream_id_type stream_id, const LPA_type lpa)
	{
		AddressMappingDomain* domain = domains[stream_id];
		MVPN_type mvpn = get_MVPN(lpa, stream_id);

		/*This is the first time that a user request accesses this address.
		Just create an entry in cache! No flash read is needed.*/
		if (domain->GlobalTranslationDirectory[mvpn].MPPN == NO_MPPN) {
			if (!domain->CMT->Check_free_slot_availability()) {
				LPA_type evicted_lpa;
				CMTSlotType evictedItem = domain->CMT->Evict_one_slot(evicted_lpa);
				if (evictedItem.Dirty) {
					/* In order to eliminate possible race conditions for the requests that
					* will access the evicted lpa in the near future (before the translation
					* write finishes), MQSim updates GMT (the on flash mapping table) right
					* after eviction happens.*/
					domain->GlobalMappingTable[evicted_lpa].PPA = evictedItem.PPA;
					domain->GlobalMappingTable[evicted_lpa].WrittenStateBitmap = evictedItem.WrittenStateBitmap;
					if (domain->GlobalMappingTable[evicted_lpa].TimeStamp > CurrentTimeStamp)
						throw std::logic_error("Unexpected situation occurred in handling GMT!");
					domain->GlobalMappingTable[evicted_lpa].TimeStamp = CurrentTimeStamp;
					generate_flash_writeback_request_for_mapping_data(stream_id, evicted_lpa);
				}
			}
			domain->CMT->Reserve_slot_for_lpn(stream_id, lpa);
			domain->CMT->Insert_new_mapping_info(stream_id, lpa, NO_PPA, UNWRITTEN_LOGICAL_PAGE);
			
			return true;
		}

		/*A read transaction is already under process to retrieve the MVP content.
		* This situation may happen in two different cases:
		* 1. A read has been issued to retrieve unchanged parts of the mapping data and merge them
		*     with the changed parts (i.e., an update read of MVP). This read will be followed
		*     by a writeback of MVP content to a new flash page.
		* 2. A read has been issued to retrieve the mapping data for some previous user requests*/
		if (domain->ArrivingMappingEntries.find(mvpn) != domain->ArrivingMappingEntries.end())
		{
			if (domain->CMT->Is_slot_reserved_for_lpn_and_waiting(stream_id, lpa)) {
				return false;
			} else { //An entry should be created in the cache
				if (!domain->CMT->Check_free_slot_availability()) {
					LPA_type evicted_lpa;
					CMTSlotType evictedItem = domain->CMT->Evict_one_slot(evicted_lpa);
					if (evictedItem.Dirty) {
						/* In order to eliminate possible race conditions for the requests that
						* will access the evicted lpa in the near future (before the translation
						* write finishes), MQSim updates GMT (the on flash mapping table) right
						* after eviction happens.*/
						domain->GlobalMappingTable[evicted_lpa].PPA = evictedItem.PPA;
						domain->GlobalMappingTable[evicted_lpa].WrittenStateBitmap = evictedItem.WrittenStateBitmap;
						if (domain->GlobalMappingTable[evicted_lpa].TimeStamp > CurrentTimeStamp)
							throw std::logic_error("Unexpected situation occured in handling GMT!");
						domain->GlobalMappingTable[evicted_lpa].TimeStamp = CurrentTimeStamp;
						generate_flash_writeback_request_for_mapping_data(stream_id, evicted_lpa);
					}
				}
				domain->CMT->Reserve_slot_for_lpn(stream_id, lpa);
				domain->ArrivingMappingEntries.insert(std::pair<MVPN_type, LPA_type>(mvpn, lpa));

				return false;
			}
		}

		/*MQSim assumes that the data of all departing (evicted from CMT) translation pages are in memory, until
		the flash program operation finishes and the entry it is cleared from DepartingMappingEntries.*/
		if (domain->DepartingMappingEntries.find(mvpn) != domain->DepartingMappingEntries.end()) {
			if (!domain->CMT->Check_free_slot_availability()) {
				LPA_type evicted_lpa;
				CMTSlotType evictedItem = domain->CMT->Evict_one_slot(evicted_lpa);
				if (evictedItem.Dirty) {
					/* In order to eliminate possible race conditions for the requests that
					* will access the evicted lpa in the near future (before the translation
					* write finishes), MQSim updates GMT (the on flash mapping table) right
					* after eviction happens.*/
					domain->GlobalMappingTable[evicted_lpa].PPA = evictedItem.PPA;
					domain->GlobalMappingTable[evicted_lpa].WrittenStateBitmap = evictedItem.WrittenStateBitmap;
					if (domain->GlobalMappingTable[evicted_lpa].TimeStamp > CurrentTimeStamp)
						throw std::logic_error("Unexpected situation occured in handling GMT!");
					domain->GlobalMappingTable[lpa].TimeStamp = CurrentTimeStamp;
					generate_flash_writeback_request_for_mapping_data(stream_id, evicted_lpa);
				}
			}
			domain->CMT->Reserve_slot_for_lpn(stream_id, lpa);
			/*Hack: since we do not actually save the values of translation requests, we copy the mapping
			data from GlobalMappingTable (which actually must be stored on flash)*/
			domain->CMT->Insert_new_mapping_info(stream_id, lpa,
				domain->GlobalMappingTable[lpa].PPA, domain->GlobalMappingTable[lpa].WrittenStateBitmap);
			
			return true;
		}

		//Non of the above options provide mapping data. So, MQSim, must read the translation data from flash memory
		if (!domain->CMT->Check_free_slot_availability()) {
			LPA_type evicted_lpa;
			CMTSlotType evictedItem = domain->CMT->Evict_one_slot(evicted_lpa);
			if (evictedItem.Dirty) {
				/* In order to eliminate possible race conditions for the requests that
				* will access the evicted lpa in the near future (before the translation
				* write finishes), MQSim updates GMT (the on flash mapping table) right
				* after eviction happens.*/
				domain->GlobalMappingTable[evicted_lpa].PPA = evictedItem.PPA;
				domain->GlobalMappingTable[evicted_lpa].WrittenStateBitmap = evictedItem.WrittenStateBitmap;
				if (domain->GlobalMappingTable[evicted_lpa].TimeStamp > CurrentTimeStamp) {
					throw std::logic_error("Unexpected situation occured in handling GMT!");
				}
				domain->GlobalMappingTable[evicted_lpa].TimeStamp = CurrentTimeStamp;
				generate_flash_writeback_request_for_mapping_data(stream_id, evicted_lpa);
			}
		}
		domain->CMT->Reserve_slot_for_lpn(stream_id, lpa);
		generate_flash_read_request_for_mapping_data(stream_id, lpa);//consult GTD and create read transaction
		
		return false;
	}

// Assembly:
pushq %rbp
pushq %r15
pushq %r14
pushq %r13
pushq %r12
pushq %rbx
subq $0x48, %rsp
movq %rdx, %rbx
movl %esi, %ebp
movq %rdi, %r15
movq 0xa8(%rdi), %rax
movl %esi, %ecx
movq (%rax,%rcx,8), %r14
movl 0xc0(%rdi), %ecx
movq %rdx, %rax
xorl %edx, %edx
divq %rcx
movq %rax, %r12
movq (%r14), %rax
movl %r12d, %ecx
shlq $0x4, %rcx
cmpl $-0x1, (%rax,%rcx)
je 0x2b62a
movq 0x98(%r14), %rdx
leaq 0x90(%r14), %rax
movq %rax, %rcx
testq %rdx, %rdx
je 0x2b53d
movq %rax, %rcx
xorl %esi, %esi
cmpl %r12d, 0x20(%rdx)
setb %sil
cmovaeq %rdx, %rcx
movq 0x10(%rdx,%rsi,8), %rdx
testq %rdx, %rdx
jne 0x2b525
movq %rax, %rdx
cmpq %rax, %rcx
je 0x2b550
cmpl %r12d, 0x20(%rcx)
cmovaq %rax, %rcx
movq %rcx, %rdx
cmpq %rax, %rdx
je 0x2b6d4
movq 0x10(%r14), %r13
movzwl %bp, %ebp
movq %r13, %rdi
movl %ebp, %esi
movq %rbx, %rdx
callq 0x2994c
testb %al, %al
jne 0x2b86f
movl 0x50(%r13), %eax
cmpq %rax, 0x18(%r13)
jb 0x2b5fc
leaq 0x10(%rsp), %rdi
movq %rsp, %rdx
movq %r13, %rsi
callq 0x29b34
leaq 0x10(%rsp), %rax
cmpb $0x1, 0x10(%rax)
jne 0x2b5fc
movq 0x20(%r14), %rax
movq (%rsp), %rcx
movq %rcx, 0x40(%rsp)
leaq (%rcx,%rcx,2), %r13
movaps 0x10(%rsp), %xmm0
movups %xmm0, (%rax,%r13,8)
movq 0x10(%rax,%r13,8), %rax
movq %rax, 0x8(%rsp)
callq 0x281b4
movq %rax, %rdi
callq 0x285a6
cmpq %rax, 0x8(%rsp)
ja 0x2b89e
callq 0x281b4
movq %rax, %rdi
callq 0x285a6
movq 0x20(%r14), %rcx
movq %rax, 0x10(%rcx,%r13,8)
movq %r15, %rdi
movl %ebp, %esi
movq 0x40(%rsp), %rdx
callq 0x2e456
movq 0x10(%r14), %rdi
addq $0x88, %r14
movl %ebp, %esi
movq %rbx, %rdx
callq 0x299cc
leaq 0x10(%rsp), %rsi
movl %r12d, (%rsi)
movq %rbx, 0x8(%rsi)
movq %r14, %rdi
callq 0x31a40
jmp 0x2b86f
movq 0x10(%r14), %rsi
movl 0x50(%rsi), %eax
cmpq %rax, 0x18(%rsi)
jb 0x2b6ab
leaq 0x10(%rsp), %r12
movq %rsp, %rdx
movq %r12, %rdi
callq 0x29b34
cmpb $0x1, 0x10(%r12)
jne 0x2b6ab
movq 0x20(%r14), %rax
movq (%rsp), %rcx
movq %rcx, 0x8(%rsp)
leaq (%rcx,%rcx,2), %r13
movaps 0x10(%rsp), %xmm0
movups %xmm0, (%rax,%r13,8)
movq 0x10(%rax,%r13,8), %r12
callq 0x281b4
movq %rax, %rdi
callq 0x285a6
cmpq %rax, %r12
ja 0x2b880
callq 0x281b4
movq %rax, %rdi
callq 0x285a6
movq 0x20(%r14), %rcx
movq %rax, 0x10(%rcx,%r13,8)
movzwl %bp, %esi
movq %r15, %rdi
movq 0x8(%rsp), %rdx
callq 0x2e456
movq 0x10(%r14), %rdi
movzwl %bp, %ebp
movl %ebp, %esi
movq %rbx, %rdx
callq 0x299cc
movq 0x10(%r14), %rdi
movl %ebp, %esi
movq %rbx, %rdx
movq $-0x1, %rcx
xorl %r8d, %r8d
jmp 0x2b7cc
movq 0xc8(%r14), %rdx
leaq 0xc0(%r14), %rax
movq %rax, %rcx
testq %rdx, %rdx
je 0x2b705
movq %rax, %rcx
xorl %esi, %esi
cmpl %r12d, 0x20(%rdx)
setb %sil
cmovaeq %rdx, %rcx
movq 0x10(%rdx,%rsi,8), %rdx
testq %rdx, %rdx
jne 0x2b6ed
movq %rax, %rdx
cmpq %rax, %rcx
je 0x2b718
cmpl %r12d, 0x20(%rcx)
cmovaq %rax, %rcx
movq %rcx, %rdx
movq 0x10(%r14), %rsi
movq 0x18(%rsi), %rcx
movl 0x50(%rsi), %edi
cmpq %rax, %rdx
je 0x2b7d8
cmpq %rdi, %rcx
jb 0x2b7a1
leaq 0x10(%rsp), %r12
movq %rsp, %rdx
movq %r12, %rdi
callq 0x29b34
cmpb $0x1, 0x10(%r12)
jne 0x2b7a1
movq 0x20(%r14), %rax
movq (%rsp), %r12
leaq (%r12,%r12,2), %rcx
movaps 0x10(%rsp), %xmm0
movups %xmm0, (%rax,%rcx,8)
movq 0x10(%rax,%rcx,8), %r13
callq 0x281b4
movq %rax, %rdi
callq 0x285a6
cmpq %rax, %r13
ja 0x2b8bc
callq 0x281b4
movq %rax, %rdi
callq 0x285a6
movq 0x20(%r14), %rcx
leaq (%rbx,%rbx,2), %rdx
movq %rax, 0x10(%rcx,%rdx,8)
movzwl %bp, %esi
movq %r15, %rdi
movq %r12, %rdx
callq 0x2e456
movq 0x10(%r14), %rdi
movzwl %bp, %ebp
movl %ebp, %esi
movq %rbx, %rdx
callq 0x299cc
movq 0x10(%r14), %rdi
movq 0x20(%r14), %rax
leaq (%rbx,%rbx,2), %rdx
movq (%rax,%rdx,8), %rcx
movq 0x8(%rax,%rdx,8), %r8
movl %ebp, %esi
movq %rbx, %rdx
callq 0x2986e
movb $0x1, %al
jmp 0x2b871
cmpq %rdi, %rcx
jb 0x2b851
leaq 0x10(%rsp), %r12
movq %rsp, %rdx
movq %r12, %rdi
callq 0x29b34
cmpb $0x1, 0x10(%r12)
jne 0x2b851
movq 0x20(%r14), %rax
movq (%rsp), %rcx
movq %rcx, 0x8(%rsp)
leaq (%rcx,%rcx,2), %r13
movaps 0x10(%rsp), %xmm0
movups %xmm0, (%rax,%r13,8)
movq 0x10(%rax,%r13,8), %r12
callq 0x281b4
movq %rax, %rdi
callq 0x285a6
cmpq %rax, %r12
ja 0x2b8da
callq 0x281b4
movq %rax, %rdi
callq 0x285a6
movq 0x20(%r14), %rcx
movq %rax, 0x10(%rcx,%r13,8)
movzwl %bp, %esi
movq %r15, %rdi
movq 0x8(%rsp), %rdx
callq 0x2e456
movq 0x10(%r14), %rdi
movzwl %bp, %ebp
movl %ebp, %esi
movq %rbx, %rdx
callq 0x299cc
movq %r15, %rdi
movl %ebp, %esi
movq %rbx, %rdx
callq 0x2f518
xorl %eax, %eax
addq $0x48, %rsp
popq %rbx
popq %r12
popq %r13
popq %r14
popq %r15
popq %rbp
retq
movl $0x10, %edi
callq 0x71d0
movq %rax, %r14
leaq 0x2d32a(%rip), %rsi     # 0x58bbe
movq %rax, %rdi
callq 0x7500
jmp 0x2b8f6
movl $0x10, %edi
callq 0x71d0
movq %rax, %r14
leaq 0x2d194(%rip), %rsi     # 0x58a46
movq %rax, %rdi
callq 0x7500
jmp 0x2b8f6
movl $0x10, %edi
callq 0x71d0
movq %rax, %r14
leaq 0x2d176(%rip), %rsi     # 0x58a46
movq %rax, %rdi
callq 0x7500
jmp 0x2b8f6
movl $0x10, %edi
callq 0x71d0
movq %rax, %r14
leaq 0x2d158(%rip), %rsi     # 0x58a46
movq %rax, %rdi
callq 0x7500
movq 0x436c3(%rip), %rsi     # 0x6efc0
movq 0x43684(%rip), %rdx     # 0x6ef88
movq %r14, %rdi
callq 0x75e0
jmp 0x2b912
jmp 0x2b912
jmp 0x2b912
movq %rax, %rbx
movq %r14, %rdi
callq 0x72c0
movq %rbx, %rdi
callq 0x7620
nop