// File: /workspace/github_cpp_makefile_star2_O2/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
movl %eax, 0xc(%rsp)
movq (%r13), %rcx
movl %eax, %eax
shlq $0x4, %rax
cmpl $-0x1, (%rcx,%rax)
je 0x224c4
leaq 0x88(%r13), %r15
leaq 0xc(%rsp), %rsi
movq %r15, %rdi
callq 0x28390
leaq 0x90(%r13), %rcx
cmpq %rcx, %rax
je 0x2256c
movq 0x10(%r13), %rdi
movzwl %bp, %ebp
movl %ebp, %esi
movq %rbx, %rdx
callq 0x20c50
testb %al, %al
jne 0x226df
movq 0x10(%r13), %rsi
movl 0x50(%rsi), %eax
cmpq %rax, 0x18(%rsi)
jb 0x2249b
leaq 0x20(%rsp), %r12
movq %rsp, %rdx
movq %r12, %rdi
callq 0x20d7a
cmpb $0x1, 0x10(%r12)
jne 0x22497
movq 0x20(%r13), %rax
movq (%rsp), %rcx
movq %rcx, 0x18(%rsp)
imulq $0x18, %rcx, %r12
movaps 0x20(%rsp), %xmm0
movups %xmm0, (%rax,%r12)
movq 0x10(%rax,%r12), %rax
movq %rax, 0x10(%rsp)
callq 0x1f784
movq %rax, %rdi
callq 0x1fafc
cmpq %rax, 0x10(%rsp)
ja 0x2270c
callq 0x1f784
movq %rax, %rdi
callq 0x1fafc
movq 0x20(%r13), %rcx
movq %rax, 0x10(%rcx,%r12)
movq %r14, %rdi
movl %ebp, %esi
movq 0x18(%rsp), %rdx
callq 0x24e68
movq 0x10(%r13), %rsi
movq %rsi, %rdi
movl %ebp, %esi
movq %rbx, %rdx
callq 0x20c7c
movl 0xc(%rsp), %eax
leaq 0x20(%rsp), %rsi
movl %eax, (%rsi)
movq %rbx, 0x8(%rsi)
movq %r15, %rdi
callq 0x283e2
jmp 0x226df
movq 0x10(%r13), %rsi
movl 0x50(%rsi), %eax
cmpq %rax, 0x18(%rsi)
jb 0x22548
leaq 0x20(%rsp), %r15
movq %rsp, %rdx
movq %r15, %rdi
callq 0x20d7a
cmpb $0x1, 0x10(%r15)
jne 0x22544
movq 0x20(%r13), %rax
movq (%rsp), %rcx
movq %rcx, 0x10(%rsp)
imulq $0x18, %rcx, %r12
movaps 0x20(%rsp), %xmm0
movups %xmm0, (%rax,%r12)
movq 0x10(%rax,%r12), %r15
callq 0x1f784
movq %rax, %rdi
callq 0x1fafc
cmpq %rax, %r15
ja 0x226f0
callq 0x1f784
movq %rax, %rdi
callq 0x1fafc
movq 0x20(%r13), %rcx
movq %rax, 0x10(%rcx,%r12)
movzwl %bp, %esi
movq %r14, %rdi
movq 0x10(%rsp), %rdx
callq 0x24e68
movq 0x10(%r13), %rsi
movzwl %bp, %ebp
movq %rsi, %rdi
movl %ebp, %esi
movq %rbx, %rdx
callq 0x20c7c
movq 0x10(%r13), %rdi
pushq $-0x1
popq %rcx
movl %ebp, %esi
movq %rbx, %rdx
xorl %r8d, %r8d
jmp 0x2263a
leaq 0xb8(%r13), %rdi
leaq 0xc(%rsp), %rsi
callq 0x28510
leaq 0xc0(%r13), %rdi
movq 0x10(%r13), %rsi
movq 0x18(%rsi), %rcx
movl 0x50(%rsi), %edx
cmpq %rdi, %rax
je 0x22646
cmpq %rdx, %rcx
jb 0x22610
leaq 0x20(%rsp), %r15
movq %rsp, %rdx
movq %r15, %rdi
callq 0x20d7a
cmpb $0x1, 0x10(%r15)
jne 0x2260c
movq 0x20(%r13), %rax
movq (%rsp), %r15
imulq $0x18, %r15, %rcx
movaps 0x20(%rsp), %xmm0
movups %xmm0, (%rax,%rcx)
movq 0x10(%rax,%rcx), %r12
callq 0x1f784
movq %rax, %rdi
callq 0x1fafc
cmpq %rax, %r12
ja 0x22728
callq 0x1f784
movq %rax, %rdi
callq 0x1fafc
movq 0x20(%r13), %rcx
imulq $0x18, %rbx, %rdx
movq %rax, 0x10(%rcx,%rdx)
movzwl %bp, %esi
movq %r14, %rdi
movq %r15, %rdx
callq 0x24e68
movq 0x10(%r13), %rsi
movzwl %bp, %ebp
movq %rsi, %rdi
movl %ebp, %esi
movq %rbx, %rdx
callq 0x20c7c
movq 0x10(%r13), %rdi
movq 0x20(%r13), %rax
imulq $0x18, %rbx, %rdx
movq (%rax,%rdx), %rcx
movq 0x8(%rax,%rdx), %r8
movl %ebp, %esi
movq %rbx, %rdx
callq 0x20bba
movb $0x1, %al
jmp 0x226e1
cmpq %rdx, %rcx
jb 0x226c2
leaq 0x20(%rsp), %r15
movq %rsp, %rdx
movq %r15, %rdi
callq 0x20d7a
cmpb $0x1, 0x10(%r15)
jne 0x226be
movq 0x20(%r13), %rax
movq (%rsp), %rcx
movq %rcx, 0x10(%rsp)
imulq $0x18, %rcx, %r12
movaps 0x20(%rsp), %xmm0
movups %xmm0, (%rax,%r12)
movq 0x10(%rax,%r12), %r15
callq 0x1f784
movq %rax, %rdi
callq 0x1fafc
cmpq %rax, %r15
ja 0x22744
callq 0x1f784
movq %rax, %rdi
callq 0x1fafc
movq 0x20(%r13), %rcx
movq %rax, 0x10(%rcx,%r12)
movzwl %bp, %esi
movq %r14, %rdi
movq 0x10(%rsp), %rdx
callq 0x24e68
movq 0x10(%r13), %rsi
movzwl %bp, %ebp
movq %rsi, %rdi
movl %ebp, %esi
movq %rbx, %rdx
callq 0x20c7c
movq %r14, %rdi
movl %ebp, %esi
movq %rbx, %rdx
callq 0x25e2e
xorl %eax, %eax
addq $0x48, %rsp
popq %rbx
popq %r12
popq %r13
popq %r14
popq %r15
popq %rbp
retq
pushq $0x10
popq %rdi
callq 0x71b0
movq %rax, %r14
leaq 0x2438c(%rip), %rsi     # 0x46a8e
movq %rax, %rdi
callq 0x74b0
jmp 0x2275e
pushq $0x10
popq %rdi
callq 0x71b0
movq %rax, %r14
leaq 0x241f8(%rip), %rsi     # 0x46916
movq %rax, %rdi
callq 0x74b0
jmp 0x2275e
pushq $0x10
popq %rdi
callq 0x71b0
movq %rax, %r14
leaq 0x241dc(%rip), %rsi     # 0x46916
movq %rax, %rdi
callq 0x74b0
jmp 0x2275e
pushq $0x10
popq %rdi
callq 0x71b0
movq %rax, %r14
leaq 0x241c0(%rip), %rsi     # 0x46916
movq %rax, %rdi
callq 0x74b0
movq 0x3f85b(%rip), %rsi     # 0x61fc0
movq 0x3f804(%rip), %rdx     # 0x61f70
movq %r14, %rdi
callq 0x7590
jmp 0x2277a
jmp 0x2277a
jmp 0x2277a
movq %rax, %rbx
movq %r14, %rdi
callq 0x72a0
movq %rbx, %rdi
callq 0x75d0
nop