// 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::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, %r14
movq 0xa8(%rdi), %rax
movl %esi, %ecx
movq (%rax,%rcx,8), %r13
movl 0xc0(%rdi), %ecx
movq %rdx, %rax
xorl %edx, %edx
divq %rcx
movq %rax, %r15
movq (%r13), %rax
movl %r15d, %ecx
shlq $0x4, %rcx
cmpl $-0x1, (%rax,%rcx)
je 0x2b0de
movq 0x98(%r13), %rax
testq %rax, %rax
je 0x2aff9
leaq 0x88(%r13), %r12
leaq 0x90(%r13), %rdx
movq %rdx, %rcx
xorl %esi, %esi
cmpl %r15d, 0x20(%rax)
setb %sil
cmovaeq %rax, %rcx
movq 0x10(%rax,%rsi,8), %rax
testq %rax, %rax
jne 0x2afd2
cmpq %rdx, %rcx
je 0x2aff9
cmpl %r15d, 0x20(%rcx)
jbe 0x2b18a
movq 0xc8(%r13), %rax
testq %rax, %rax
je 0x2b036
leaq 0xc0(%r13), %rdx
movq %rdx, %rcx
xorl %esi, %esi
cmpl %r15d, 0x20(%rax)
setb %sil
cmovaeq %rax, %rcx
movq 0x10(%rax,%rsi,8), %rax
testq %rax, %rax
jne 0x2b00f
cmpq %rdx, %rcx
je 0x2b036
cmpl %r15d, 0x20(%rcx)
jbe 0x2b261
movq 0x10(%r13), %rsi
movl 0x50(%rsi), %eax
cmpq %rax, 0x18(%rsi)
jb 0x2b0ba
leaq 0x10(%rsp), %r15
movq %rsp, %rdx
movq %r15, %rdi
callq 0x2972e
cmpb $0x1, 0x10(%r15)
jne 0x2b0b6
movq 0x20(%r13), %rax
movq (%rsp), %rcx
movq %rcx, 0x8(%rsp)
leaq (%rcx,%rcx,2), %r12
movaps 0x10(%rsp), %xmm0
movups %xmm0, (%rax,%r12,8)
movq 0x10(%rax,%r12,8), %r15
callq 0x28018
movq %rax, %rdi
callq 0x2841a
cmpq %rax, %r15
ja 0x2b321
callq 0x28018
movq %rax, %rdi
callq 0x2841a
movq 0x20(%r13), %rcx
movq %rax, 0x10(%rcx,%r12,8)
movzwl %bp, %esi
movq %r14, %rdi
movq 0x8(%rsp), %rdx
callq 0x2de74
movq 0x10(%r13), %rsi
movzwl %bp, %ebp
movq %rsi, %rdi
movl %ebp, %esi
movq %rbx, %rdx
callq 0x2960c
movq %r14, %rdi
movl %ebp, %esi
movq %rbx, %rdx
callq 0x2eef6
xorl %eax, %eax
jmp 0x2b312
movq 0x10(%r13), %rsi
movl 0x50(%rsi), %eax
cmpq %rax, 0x18(%rsi)
jb 0x2b162
leaq 0x10(%rsp), %r15
movq %rsp, %rdx
movq %r15, %rdi
callq 0x2972e
cmpb $0x1, 0x10(%r15)
jne 0x2b15e
movq 0x20(%r13), %rax
movq (%rsp), %rcx
movq %rcx, 0x8(%rsp)
leaq (%rcx,%rcx,2), %r12
movaps 0x10(%rsp), %xmm0
movups %xmm0, (%rax,%r12,8)
movq 0x10(%rax,%r12,8), %r15
callq 0x28018
movq %rax, %rdi
callq 0x2841a
cmpq %rax, %r15
ja 0x2b33f
callq 0x28018
movq %rax, %rdi
callq 0x2841a
movq 0x20(%r13), %rcx
movq %rax, 0x10(%rcx,%r12,8)
movzwl %bp, %esi
movq %r14, %rdi
movq 0x8(%rsp), %rdx
callq 0x2de74
movq 0x10(%r13), %rsi
movzwl %bp, %ebp
movq %rsi, %rdi
movl %ebp, %esi
movq %rbx, %rdx
callq 0x2960c
movq 0x10(%r13), %rdi
movl %ebp, %esi
movq %rbx, %rdx
movq $-0x1, %rcx
xorl %r8d, %r8d
jmp 0x2b30b
movq 0x10(%r13), %rdi
movzwl %bp, %ebp
movl %ebp, %esi
movq %rbx, %rdx
callq 0x295e0
testb %al, %al
jne 0x2b0d7
movq 0x10(%r13), %rsi
movl 0x50(%rsi), %eax
cmpq %rax, 0x18(%rsi)
jb 0x2b23b
leaq 0x10(%rsp), %rdi
movq %rsp, %rdx
callq 0x2972e
leaq 0x10(%rsp), %rax
cmpb $0x1, 0x10(%rax)
jne 0x2b237
movq 0x20(%r13), %rax
movq (%rsp), %rcx
movq %rcx, 0x40(%rsp)
leaq (%rcx,%rcx,2), %rcx
movaps 0x10(%rsp), %xmm0
movups %xmm0, (%rax,%rcx,8)
movq %rcx, 0x38(%rsp)
movq 0x10(%rax,%rcx,8), %rax
movq %rax, 0x8(%rsp)
callq 0x28018
movq %rax, %rdi
callq 0x2841a
cmpq %rax, 0x8(%rsp)
ja 0x2b37b
callq 0x28018
movq %rax, %rdi
callq 0x2841a
movq 0x20(%r13), %rcx
movq 0x38(%rsp), %rdx
movq %rax, 0x10(%rcx,%rdx,8)
movq %r14, %rdi
movl %ebp, %esi
movq 0x40(%rsp), %rdx
callq 0x2de74
movq 0x10(%r13), %rsi
movq %rsi, %rdi
movl %ebp, %esi
movq %rbx, %rdx
callq 0x2960c
leaq 0x10(%rsp), %rsi
movl %r15d, (%rsi)
movq %rbx, 0x8(%rsi)
movq %r12, %rdi
callq 0x31222
jmp 0x2b0d7
movq 0x10(%r13), %rsi
movl 0x50(%rsi), %eax
cmpq %rax, 0x18(%rsi)
jb 0x2b2e1
leaq 0x10(%rsp), %r15
movq %rsp, %rdx
movq %r15, %rdi
callq 0x2972e
cmpb $0x1, 0x10(%r15)
jne 0x2b2dd
movq 0x20(%r13), %rax
movq (%rsp), %r15
leaq (%r15,%r15,2), %rcx
movaps 0x10(%rsp), %xmm0
movups %xmm0, (%rax,%rcx,8)
movq 0x10(%rax,%rcx,8), %r12
callq 0x28018
movq %rax, %rdi
callq 0x2841a
cmpq %rax, %r12
ja 0x2b35d
callq 0x28018
movq %rax, %rdi
callq 0x2841a
movq 0x20(%r13), %rcx
leaq (%rbx,%rbx,2), %rdx
movq %rax, 0x10(%rcx,%rdx,8)
movzwl %bp, %esi
movq %r14, %rdi
movq %r15, %rdx
callq 0x2de74
movq 0x10(%r13), %rsi
movzwl %bp, %ebp
movq %rsi, %rdi
movl %ebp, %esi
movq %rbx, %rdx
callq 0x2960c
movq 0x10(%r13), %rdi
movq 0x20(%r13), %rax
leaq (%rbx,%rbx,2), %rdx
movq (%rax,%rdx,8), %rcx
movq 0x8(%rax,%rdx,8), %r8
movl %ebp, %esi
movq %rbx, %rdx
callq 0x29548
movb $0x1, %al
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 0x2d711(%rip), %rsi     # 0x58a46
movq %rax, %rdi
callq 0x7500
jmp 0x2b397
movl $0x10, %edi
callq 0x71d0
movq %rax, %r14
leaq 0x2d86b(%rip), %rsi     # 0x58bbe
movq %rax, %rdi
callq 0x7500
jmp 0x2b397
movl $0x10, %edi
callq 0x71d0
movq %rax, %r14
leaq 0x2d6d5(%rip), %rsi     # 0x58a46
movq %rax, %rdi
callq 0x7500
jmp 0x2b397
movl $0x10, %edi
callq 0x71d0
movq %rax, %r14
leaq 0x2d6b7(%rip), %rsi     # 0x58a46
movq %rax, %rdi
callq 0x7500
movq 0x43c22(%rip), %rsi     # 0x6efc0
movq 0x43bdb(%rip), %rdx     # 0x6ef80
movq %r14, %rdi
callq 0x75e0
jmp 0x2b3b3
jmp 0x2b3b3
jmp 0x2b3b3
movq %rax, %rbx
movq %r14, %rdi
callq 0x72c0
movq %rbx, %rdi
callq 0x7620