// File: 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:
subq $0x188, %rsp            # imm = 0x188
movw %si, %ax
movq %rdi, 0x178(%rsp)
movw %ax, 0x176(%rsp)
movq %rdx, 0x168(%rsp)
movq 0x178(%rsp), %rdi
movq %rdi, 0x48(%rsp)
movq 0xa8(%rdi), %rax
movzwl 0x176(%rsp), %ecx
movq (%rax,%rcx,8), %rax
movq %rax, 0x160(%rsp)
movq 0x168(%rsp), %rsi
movzwl 0x176(%rsp), %edx
callq 0x5a1d0
movl %eax, 0x15c(%rsp)
movq 0x160(%rsp), %rax
movq (%rax), %rax
movl 0x15c(%rsp), %ecx
shlq $0x4, %rcx
addq %rcx, %rax
movl (%rax), %eax
movl $0xffffffff, %ecx       # imm = 0xFFFFFFFF
cmpq %rcx, %rax
jne 0x4dc33
movq 0x160(%rsp), %rax
movq 0x10(%rax), %rdi
callq 0x59800
testb $0x1, %al
jne 0x4dbd2
movq 0x160(%rsp), %rax
movq 0x10(%rax), %rsi
leaq 0x128(%rsp), %rdi
leaq 0x150(%rsp), %rdx
callq 0x4ab80
testb $0x1, 0x138(%rsp)
je 0x4dbd0
movq 0x128(%rsp), %rcx
movq 0x160(%rsp), %rax
movq 0x20(%rax), %rax
imulq $0x18, 0x150(%rsp), %rdx
addq %rdx, %rax
movq %rcx, (%rax)
movq 0x130(%rsp), %rcx
movq 0x160(%rsp), %rax
movq 0x20(%rax), %rax
imulq $0x18, 0x150(%rsp), %rdx
addq %rdx, %rax
movq %rcx, 0x8(%rax)
movq 0x160(%rsp), %rax
movq 0x20(%rax), %rax
imulq $0x18, 0x150(%rsp), %rcx
addq %rcx, %rax
movq 0x10(%rax), %rax
movq %rax, 0x40(%rsp)
callq 0x46500
movq %rax, %rdi
callq 0x46c50
movq %rax, %rcx
movq 0x40(%rsp), %rax
cmpq %rcx, %rax
jbe 0x4db87
movl $0x10, %edi
callq 0x8200
movq %rax, %rdi
movq %rdi, %rax
movq %rax, 0x38(%rsp)
leaq 0x5f0e9(%rip), %rsi     # 0xacc2e
callq 0x8610
jmp 0x4db4c
movq 0x38(%rsp), %rdi
movq 0x8c468(%rip), %rsi     # 0xd9fc0
movq 0x8c431(%rip), %rdx     # 0xd9f90
callq 0x8710
movq 0x38(%rsp), %rdi
movq %rax, %rcx
movl %edx, %eax
movq %rcx, 0x120(%rsp)
movl %eax, 0x11c(%rsp)
callq 0x8330
jmp 0x4e2bf
callq 0x46500
movq %rax, %rdi
callq 0x46c50
movq 0x48(%rsp), %rdi
movq %rax, %rcx
movq 0x160(%rsp), %rax
movq 0x20(%rax), %rax
imulq $0x18, 0x150(%rsp), %rdx
addq %rdx, %rax
movq %rcx, 0x10(%rax)
movw 0x176(%rsp), %ax
movq 0x150(%rsp), %rdx
movzwl %ax, %esi
callq 0x55480
jmp 0x4dbd2
movq 0x160(%rsp), %rax
movq 0x10(%rax), %rdi
movw 0x176(%rsp), %ax
movq 0x168(%rsp), %rdx
movzwl %ax, %esi
callq 0x4a960
movq 0x160(%rsp), %rax
movq 0x10(%rax), %rdi
movw 0x176(%rsp), %ax
movq 0x168(%rsp), %rdx
movq $-0x1, %rcx
xorl %esi, %esi
movl %esi, %r8d
movzwl %ax, %esi
callq 0x4a760
movb $0x1, 0x187(%rsp)
jmp 0x4e2ae
movq 0x160(%rsp), %rdi
addq $0x88, %rdi
leaq 0x15c(%rsp), %rsi
callq 0x5a220
movq %rax, 0x110(%rsp)
movq 0x160(%rsp), %rdi
addq $0x88, %rdi
callq 0x5a250
movq %rax, 0x108(%rsp)
leaq 0x110(%rsp), %rdi
leaq 0x108(%rsp), %rsi
callq 0x5a200
testb $0x1, %al
jne 0x4dc91
jmp 0x4deb6
movq 0x160(%rsp), %rax
movq 0x10(%rax), %rdi
movw 0x176(%rsp), %ax
movq 0x168(%rsp), %rdx
movzwl %ax, %esi
callq 0x4a8c0
testb $0x1, %al
jne 0x4dcbb
jmp 0x4dcc8
movb $0x0, 0x187(%rsp)
jmp 0x4e2ae
movq 0x160(%rsp), %rax
movq 0x10(%rax), %rdi
callq 0x59800
testb $0x1, %al
jne 0x4de3b
movq 0x160(%rsp), %rax
movq 0x10(%rax), %rsi
leaq 0xd8(%rsp), %rdi
leaq 0x100(%rsp), %rdx
callq 0x4ab80
testb $0x1, 0xe8(%rsp)
je 0x4de39
movq 0xd8(%rsp), %rcx
movq 0x160(%rsp), %rax
movq 0x20(%rax), %rax
imulq $0x18, 0x100(%rsp), %rdx
addq %rdx, %rax
movq %rcx, (%rax)
movq 0xe0(%rsp), %rcx
movq 0x160(%rsp), %rax
movq 0x20(%rax), %rax
imulq $0x18, 0x100(%rsp), %rdx
addq %rdx, %rax
movq %rcx, 0x8(%rax)
movq 0x160(%rsp), %rax
movq 0x20(%rax), %rax
imulq $0x18, 0x100(%rsp), %rcx
addq %rcx, %rax
movq 0x10(%rax), %rax
movq %rax, 0x30(%rsp)
callq 0x46500
movq %rax, %rdi
callq 0x46c50
movq %rax, %rcx
movq 0x30(%rsp), %rax
cmpq %rcx, %rax
jbe 0x4ddf0
movl $0x10, %edi
callq 0x8200
movq %rax, %rdi
movq %rdi, %rax
movq %rax, 0x28(%rsp)
leaq 0x5ed08(%rip), %rsi     # 0xacab6
callq 0x8610
jmp 0x4ddb5
movq 0x28(%rsp), %rdi
movq 0x8c1ff(%rip), %rsi     # 0xd9fc0
movq 0x8c1c8(%rip), %rdx     # 0xd9f90
callq 0x8710
movq 0x28(%rsp), %rdi
movq %rax, %rcx
movl %edx, %eax
movq %rcx, 0x120(%rsp)
movl %eax, 0x11c(%rsp)
callq 0x8330
jmp 0x4e2bf
callq 0x46500
movq %rax, %rdi
callq 0x46c50
movq 0x48(%rsp), %rdi
movq %rax, %rcx
movq 0x160(%rsp), %rax
movq 0x20(%rax), %rax
imulq $0x18, 0x100(%rsp), %rdx
addq %rdx, %rax
movq %rcx, 0x10(%rax)
movw 0x176(%rsp), %ax
movq 0x100(%rsp), %rdx
movzwl %ax, %esi
callq 0x55480
jmp 0x4de3b
movq 0x160(%rsp), %rax
movq 0x10(%rax), %rdi
movw 0x176(%rsp), %ax
movq 0x168(%rsp), %rdx
movzwl %ax, %esi
callq 0x4a960
movq 0x160(%rsp), %rax
addq $0x88, %rax
movq %rax, 0x20(%rsp)
leaq 0xc8(%rsp), %rdi
leaq 0x15c(%rsp), %rsi
leaq 0x168(%rsp), %rdx
callq 0x5a2b0
movq 0x20(%rsp), %rdi
leaq 0xc8(%rsp), %rsi
callq 0x5a280
movq %rax, 0xc0(%rsp)
movb $0x0, 0x187(%rsp)
jmp 0x4e2ae
movq 0x160(%rsp), %rdi
addq $0xb8, %rdi
leaq 0x15c(%rsp), %rsi
callq 0x5a300
movq %rax, 0xb8(%rsp)
movq 0x160(%rsp), %rdi
addq $0xb8, %rdi
callq 0x5a340
movq %rax, 0xb0(%rsp)
leaq 0xb8(%rsp), %rdi
leaq 0xb0(%rsp), %rsi
callq 0x5a2e0
testb $0x1, %al
jne 0x4df14
jmp 0x4e113
movq 0x160(%rsp), %rax
movq 0x10(%rax), %rdi
callq 0x59800
testb $0x1, %al
jne 0x4e087
movq 0x160(%rsp), %rax
movq 0x10(%rax), %rsi
leaq 0x80(%rsp), %rdi
leaq 0xa8(%rsp), %rdx
callq 0x4ab80
testb $0x1, 0x90(%rsp)
je 0x4e085
movq 0x80(%rsp), %rcx
movq 0x160(%rsp), %rax
movq 0x20(%rax), %rax
imulq $0x18, 0xa8(%rsp), %rdx
addq %rdx, %rax
movq %rcx, (%rax)
movq 0x88(%rsp), %rcx
movq 0x160(%rsp), %rax
movq 0x20(%rax), %rax
imulq $0x18, 0xa8(%rsp), %rdx
addq %rdx, %rax
movq %rcx, 0x8(%rax)
movq 0x160(%rsp), %rax
movq 0x20(%rax), %rax
imulq $0x18, 0xa8(%rsp), %rcx
addq %rcx, %rax
movq 0x10(%rax), %rax
movq %rax, 0x18(%rsp)
callq 0x46500
movq %rax, %rdi
callq 0x46c50
movq %rax, %rcx
movq 0x18(%rsp), %rax
cmpq %rcx, %rax
jbe 0x4e03c
movl $0x10, %edi
callq 0x8200
movq %rax, %rdi
movq %rdi, %rax
movq %rax, 0x10(%rsp)
leaq 0x5eabc(%rip), %rsi     # 0xacab6
callq 0x8610
jmp 0x4e001
movq 0x10(%rsp), %rdi
movq 0x8bfb3(%rip), %rsi     # 0xd9fc0
movq 0x8bf7c(%rip), %rdx     # 0xd9f90
callq 0x8710
movq 0x10(%rsp), %rdi
movq %rax, %rcx
movl %edx, %eax
movq %rcx, 0x120(%rsp)
movl %eax, 0x11c(%rsp)
callq 0x8330
jmp 0x4e2bf
callq 0x46500
movq %rax, %rdi
callq 0x46c50
movq 0x48(%rsp), %rdi
movq %rax, %rcx
movq 0x160(%rsp), %rax
movq 0x20(%rax), %rax
imulq $0x18, 0x168(%rsp), %rdx
addq %rdx, %rax
movq %rcx, 0x10(%rax)
movw 0x176(%rsp), %ax
movq 0xa8(%rsp), %rdx
movzwl %ax, %esi
callq 0x55480
jmp 0x4e087
movq 0x160(%rsp), %rax
movq 0x10(%rax), %rdi
movw 0x176(%rsp), %ax
movq 0x168(%rsp), %rdx
movzwl %ax, %esi
callq 0x4a960
movq 0x160(%rsp), %rax
movq 0x10(%rax), %rdi
movw 0x176(%rsp), %ax
movq 0x168(%rsp), %rdx
movq 0x160(%rsp), %rcx
movq 0x20(%rcx), %rcx
imulq $0x18, 0x168(%rsp), %rsi
addq %rsi, %rcx
movq (%rcx), %rcx
movq 0x160(%rsp), %rsi
movq 0x20(%rsi), %rsi
imulq $0x18, 0x168(%rsp), %r8
addq %r8, %rsi
movq 0x8(%rsi), %r8
movzwl %ax, %esi
callq 0x4a760
movb $0x1, 0x187(%rsp)
jmp 0x4e2ae
movq 0x160(%rsp), %rax
movq 0x10(%rax), %rdi
callq 0x59800
testb $0x1, %al
jne 0x4e265
movq 0x160(%rsp), %rax
movq 0x10(%rax), %rsi
leaq 0x50(%rsp), %rdi
leaq 0x78(%rsp), %rdx
callq 0x4ab80
testb $0x1, 0x60(%rsp)
je 0x4e263
movq 0x50(%rsp), %rcx
movq 0x160(%rsp), %rax
movq 0x20(%rax), %rax
imulq $0x18, 0x78(%rsp), %rdx
addq %rdx, %rax
movq %rcx, (%rax)
movq 0x58(%rsp), %rcx
movq 0x160(%rsp), %rax
movq 0x20(%rax), %rax
imulq $0x18, 0x78(%rsp), %rdx
addq %rdx, %rax
movq %rcx, 0x8(%rax)
movq 0x160(%rsp), %rax
movq 0x20(%rax), %rax
imulq $0x18, 0x78(%rsp), %rcx
addq %rcx, %rax
movq 0x10(%rax), %rax
movq %rax, 0x8(%rsp)
callq 0x46500
movq %rax, %rdi
callq 0x46c50
movq %rax, %rcx
movq 0x8(%rsp), %rax
cmpq %rcx, %rax
jbe 0x4e220
movl $0x10, %edi
callq 0x8200
movq %rax, %rdi
movq %rdi, %rax
movq %rax, (%rsp)
leaq 0x5e8d6(%rip), %rsi     # 0xacab6
callq 0x8610
jmp 0x4e1e7
movq (%rsp), %rdi
movq 0x8bdce(%rip), %rsi     # 0xd9fc0
movq 0x8bd97(%rip), %rdx     # 0xd9f90
callq 0x8710
movq (%rsp), %rdi
movq %rax, %rcx
movl %edx, %eax
movq %rcx, 0x120(%rsp)
movl %eax, 0x11c(%rsp)
callq 0x8330
jmp 0x4e2bf
callq 0x46500
movq %rax, %rdi
callq 0x46c50
movq 0x48(%rsp), %rdi
movq %rax, %rcx
movq 0x160(%rsp), %rax
movq 0x20(%rax), %rax
imulq $0x18, 0x78(%rsp), %rdx
addq %rdx, %rax
movq %rcx, 0x10(%rax)
movw 0x176(%rsp), %ax
movq 0x78(%rsp), %rdx
movzwl %ax, %esi
callq 0x55480
jmp 0x4e265
movq 0x160(%rsp), %rax
movq 0x10(%rax), %rdi
movw 0x176(%rsp), %ax
movq 0x168(%rsp), %rdx
movzwl %ax, %esi
callq 0x4a960
movq 0x48(%rsp), %rdi
movw 0x176(%rsp), %ax
movq 0x168(%rsp), %rdx
movzwl %ax, %esi
callq 0x584b0
movb $0x0, 0x187(%rsp)
movb 0x187(%rsp), %al
andb $0x1, %al
addq $0x188, %rsp            # imm = 0x188
retq
movq 0x120(%rsp), %rdi
callq 0x8770
nopl (%rax)