// File: CMU-SAFARI[P]MQSim/src/ssd/Address_Mapping_Unit_Page_Level.cpp
// Function: SSD_Components::Address_Mapping_Unit_Page_Level::handle_transaction_serviced_signal_from_PHY(SSD_Components::NVM_Transaction_Flash*)
inline void Address_Mapping_Unit_Page_Level::handle_transaction_serviced_signal_from_PHY(NVM_Transaction_Flash* transaction)
	{
		//First check if the transaction source is Mapping Module
		if (transaction->Source != Transaction_Source_Type::MAPPING) {
			return;
		}

		if (_my_instance->ideal_mapping_table){
			throw std::logic_error("There should not be any flash read/write when ideal mapping is enabled!");
		}

		if (transaction->Type == Transaction_Type::WRITE) {
			_my_instance->domains[transaction->Stream_id]->DepartingMappingEntries.erase((MVPN_type)((NVM_Transaction_Flash_WR*)transaction)->Content);
		} else {
			/*If this is a read for an MVP that is required for merging unchanged mapping enries
			* (stored on flash) with those updated entries that are evicted from CMT*/
			if (((NVM_Transaction_Flash_RD*)transaction)->RelatedWrite != NULL) {
				((NVM_Transaction_Flash_RD*)transaction)->RelatedWrite->RelatedRead = NULL;
			}

			_my_instance->ftl->TSU->Prepare_for_transaction_submit();
			MVPN_type mvpn = (MVPN_type)((NVM_Transaction_Flash_RD*)transaction)->Content;
			std::multimap<MVPN_type, LPA_type>::iterator it = _my_instance->domains[transaction->Stream_id]->ArrivingMappingEntries.find(mvpn);
			while (it != _my_instance->domains[transaction->Stream_id]->ArrivingMappingEntries.end()) {
				if ((*it).first == mvpn) {
					LPA_type lpa = (*it).second;

					//This mapping entry may arrived due to an update read request that is required for merging new and old mapping entries.
					//If that is the case, we should not insert it into CMT
					if (_my_instance->domains[transaction->Stream_id]->CMT->Is_slot_reserved_for_lpn_and_waiting(transaction->Stream_id, lpa)) {
						_my_instance->domains[transaction->Stream_id]->CMT->Insert_new_mapping_info(transaction->Stream_id, lpa,
							_my_instance->domains[transaction->Stream_id]->GlobalMappingTable[lpa].PPA,
							_my_instance->domains[transaction->Stream_id]->GlobalMappingTable[lpa].WrittenStateBitmap);
						auto it2 = _my_instance->domains[transaction->Stream_id]->Waiting_unmapped_read_transactions.find(lpa);
						while (it2 != _my_instance->domains[transaction->Stream_id]->Waiting_unmapped_read_transactions.end() &&
							(*it2).first == lpa) {
							if (_my_instance->is_lpa_locked_for_gc(transaction->Stream_id, lpa)) {
								_my_instance->manage_user_transaction_facing_barrier(it2->second);
							} else {
								if (_my_instance->translate_lpa_to_ppa(transaction->Stream_id, it2->second)) {
									_my_instance->ftl->TSU->Submit_transaction(it2->second);
								}
								else {
									_my_instance->mange_unsuccessful_translation(it2->second);
								}
							}
							_my_instance->domains[transaction->Stream_id]->Waiting_unmapped_read_transactions.erase(it2++);
						}
						it2 = _my_instance->domains[transaction->Stream_id]->Waiting_unmapped_program_transactions.find(lpa);
						while (it2 != _my_instance->domains[transaction->Stream_id]->Waiting_unmapped_program_transactions.end() &&
							(*it2).first == lpa) {
							if (_my_instance->is_lpa_locked_for_gc(transaction->Stream_id, lpa)) {
								_my_instance->manage_user_transaction_facing_barrier(it2->second);
							} else {
								if (_my_instance->translate_lpa_to_ppa(transaction->Stream_id, it2->second)) {
									_my_instance->ftl->TSU->Submit_transaction(it2->second);
									if (((NVM_Transaction_Flash_WR*)it2->second)->RelatedRead != NULL) {
										_my_instance->ftl->TSU->Submit_transaction(((NVM_Transaction_Flash_WR*)it2->second)->RelatedRead);
									}
								} else {
									_my_instance->mange_unsuccessful_translation(it2->second);
								}
							}
							_my_instance->domains[transaction->Stream_id]->Waiting_unmapped_program_transactions.erase(it2++);
						}
					}
				} else {
					break;
				}
				_my_instance->domains[transaction->Stream_id]->ArrivingMappingEntries.erase(it++);
			}
			_my_instance->ftl->TSU->Schedule();
		}
	}

// Assembly:
subq $0x118, %rsp            # imm = 0x118
movq %rdi, 0x110(%rsp)
movq 0x110(%rsp), %rax
cmpl $0x3, 0x4(%rax)
je 0x58f82
jmp 0x59748
movq 0x8173f(%rip), %rax     # 0xda6c8
testb $0x1, 0x4c(%rax)
je 0x58ff6
movl $0x10, %edi
callq 0x8200
movq %rax, %rdi
movq %rdi, %rax
movq %rax, 0x88(%rsp)
leaq 0x53d46(%rip), %rsi     # 0xaccf4
callq 0x8610
jmp 0x58fb5
movq 0x88(%rsp), %rdi
movq 0x80ffc(%rip), %rsi     # 0xd9fc0
movq 0x80fc5(%rip), %rdx     # 0xd9f90
callq 0x8710
movq 0x88(%rsp), %rdi
movq %rax, %rcx
movl %edx, %eax
movq %rcx, 0x108(%rsp)
movl %eax, 0x104(%rsp)
callq 0x8330
jmp 0x59750
movq 0x110(%rsp), %rax
cmpl $0x1, 0x8(%rax)
jne 0x59050
movq 0x816bd(%rip), %rax     # 0xda6c8
movq 0xa8(%rax), %rax
movq 0x110(%rsp), %rcx
movzwl (%rcx), %ecx
movq (%rax,%rcx,8), %rdi
addq $0xb8, %rdi
movq 0x110(%rsp), %rax
movq 0x80(%rax), %rax
movl %eax, 0x100(%rsp)
leaq 0x100(%rsp), %rsi
callq 0x5d810
jmp 0x59748
movq 0x110(%rsp), %rax
cmpq $0x0, 0x88(%rax)
je 0x5907c
movq 0x110(%rsp), %rax
movq 0x88(%rax), %rax
movq $0x0, 0x88(%rax)
movq 0x81645(%rip), %rax     # 0xda6c8
movq 0x30(%rax), %rax
movq 0x50(%rax), %rdi
callq 0x59940
movq 0x110(%rsp), %rax
movq 0x80(%rax), %rax
movl %eax, 0xfc(%rsp)
movq 0x8161b(%rip), %rax     # 0xda6c8
movq 0xa8(%rax), %rax
movq 0x110(%rsp), %rcx
movzwl (%rcx), %ecx
movq (%rax,%rcx,8), %rdi
addq $0x88, %rdi
leaq 0xfc(%rsp), %rsi
callq 0x5a220
movq %rax, 0xf0(%rsp)
movq 0x815e2(%rip), %rax     # 0xda6c8
movq 0xa8(%rax), %rax
movq 0x110(%rsp), %rcx
movzwl (%rcx), %ecx
movq (%rax,%rcx,8), %rdi
addq $0x88, %rdi
callq 0x5a250
movq %rax, 0xe8(%rsp)
leaq 0xf0(%rsp), %rdi
leaq 0xe8(%rsp), %rsi
callq 0x5a200
testb $0x1, %al
jne 0x5912e
jmp 0x59733
leaq 0xf0(%rsp), %rdi
callq 0x5d840
movl (%rax), %eax
cmpl 0xfc(%rsp), %eax
jne 0x596d3
leaq 0xf0(%rsp), %rdi
callq 0x5d840
movq 0x8(%rax), %rax
movq %rax, 0xe0(%rsp)
movq 0x8155e(%rip), %rax     # 0xda6c8
movq 0xa8(%rax), %rax
movq 0x110(%rsp), %rcx
movzwl (%rcx), %ecx
movq (%rax,%rcx,8), %rax
movq 0x10(%rax), %rdi
movq 0x110(%rsp), %rax
movw (%rax), %ax
movq 0xe0(%rsp), %rdx
movzwl %ax, %esi
callq 0x4a8c0
testb $0x1, %al
jne 0x591a8
jmp 0x596d1
movq 0x81519(%rip), %rax     # 0xda6c8
movq 0xa8(%rax), %rax
movq 0x110(%rsp), %rcx
movzwl (%rcx), %ecx
movq (%rax,%rcx,8), %rax
movq 0x10(%rax), %rdi
movq 0x110(%rsp), %rax
movw (%rax), %ax
movq 0xe0(%rsp), %rdx
movq 0x814e5(%rip), %rcx     # 0xda6c8
movq 0xa8(%rcx), %rcx
movq 0x110(%rsp), %rsi
movzwl (%rsi), %esi
movq (%rcx,%rsi,8), %rcx
movq 0x20(%rcx), %rcx
imulq $0x18, 0xe0(%rsp), %rsi
addq %rsi, %rcx
movq (%rcx), %rcx
movq 0x814b5(%rip), %rsi     # 0xda6c8
movq 0xa8(%rsi), %rsi
movq 0x110(%rsp), %r8
movzwl (%r8), %r8d
movq (%rsi,%r8,8), %rsi
movq 0x20(%rsi), %rsi
imulq $0x18, 0xe0(%rsp), %r8
addq %r8, %rsi
movq 0x8(%rsi), %r8
movzwl %ax, %esi
callq 0x4a760
movq 0x8147b(%rip), %rax     # 0xda6c8
movq 0xa8(%rax), %rax
movq 0x110(%rsp), %rcx
movzwl (%rcx), %ecx
movq (%rax,%rcx,8), %rdi
addq $0x28, %rdi
leaq 0xe0(%rsp), %rsi
callq 0x5d860
movq %rax, 0xd8(%rsp)
movq 0x81445(%rip), %rax     # 0xda6c8
movq 0xa8(%rax), %rax
movq 0x110(%rsp), %rcx
movzwl (%rcx), %ecx
movq (%rax,%rcx,8), %rdi
addq $0x28, %rdi
callq 0x58e60
movq %rax, 0xd0(%rsp)
leaq 0xd8(%rsp), %rdi
leaq 0xd0(%rsp), %rsi
callq 0x58e40
movb %al, %cl
xorl %eax, %eax
testb $0x1, %cl
movb %al, 0x87(%rsp)
jne 0x592d1
jmp 0x592f3
leaq 0xd8(%rsp), %rdi
callq 0x5d890
movq (%rax), %rax
cmpq 0xe0(%rsp), %rax
sete %al
movb %al, 0x87(%rsp)
movb 0x87(%rsp), %al
testb $0x1, %al
jne 0x59303
jmp 0x5945d
movq 0x813be(%rip), %rdi     # 0xda6c8
movq 0x110(%rsp), %rax
movw (%rax), %cx
movq 0xe0(%rsp), %rdx
movq (%rdi), %rax
movzwl %cx, %esi
callq *0xe8(%rax)
testb $0x1, %al
jne 0x5932f
jmp 0x5935f
movq 0x81392(%rip), %rax     # 0xda6c8
movq %rax, 0x78(%rsp)
leaq 0xd8(%rsp), %rdi
callq 0x58e90
movq 0x78(%rsp), %rdi
movq 0x8(%rax), %rsi
movq (%rdi), %rax
callq *0xd8(%rax)
jmp 0x59401
movq 0x81362(%rip), %rax     # 0xda6c8
movq %rax, 0x68(%rsp)
movq 0x110(%rsp), %rax
movw (%rax), %ax
movw %ax, 0x76(%rsp)
leaq 0xd8(%rsp), %rdi
callq 0x58e90
movq 0x68(%rsp), %rdi
movq %rax, %rcx
movw 0x76(%rsp), %ax
movq 0x8(%rcx), %rdx
movzwl %ax, %esi
callq 0x4d800
testb $0x1, %al
jne 0x593a7
jmp 0x593d8
movq 0x8131a(%rip), %rax     # 0xda6c8
movq 0x30(%rax), %rax
movq 0x50(%rax), %rax
movq %rax, 0x60(%rsp)
leaq 0xd8(%rsp), %rdi
callq 0x58e90
movq 0x60(%rsp), %rdi
movq 0x8(%rax), %rsi
callq 0x59980
jmp 0x593ff
movq 0x812e9(%rip), %rax     # 0xda6c8
movq %rax, 0x58(%rsp)
leaq 0xd8(%rsp), %rdi
callq 0x58e90
movq 0x58(%rsp), %rdi
movq 0x8(%rax), %rsi
callq 0x4d960
jmp 0x59401
movq 0x812c0(%rip), %rax     # 0xda6c8
movq 0xa8(%rax), %rax
movq 0x110(%rsp), %rcx
movzwl (%rcx), %ecx
movq (%rax,%rcx,8), %rax
addq $0x28, %rax
movq %rax, 0x50(%rsp)
leaq 0xd8(%rsp), %rdi
xorl %esi, %esi
callq 0x58ef0
movq 0x50(%rsp), %rdi
movq %rax, 0xc8(%rsp)
movq 0xc8(%rsp), %rsi
callq 0x58eb0
movq %rax, 0xc0(%rsp)
jmp 0x5927c
movq 0x81264(%rip), %rax     # 0xda6c8
movq 0xa8(%rax), %rax
movq 0x110(%rsp), %rcx
movzwl (%rcx), %ecx
movq (%rax,%rcx,8), %rdi
addq $0x58, %rdi
leaq 0xe0(%rsp), %rsi
callq 0x5d860
movq %rax, 0xb8(%rsp)
movq 0xb8(%rsp), %rax
movq %rax, 0xd8(%rsp)
movq 0x8121e(%rip), %rax     # 0xda6c8
movq 0xa8(%rax), %rax
movq 0x110(%rsp), %rcx
movzwl (%rcx), %ecx
movq (%rax,%rcx,8), %rdi
addq $0x58, %rdi
callq 0x58e60
movq %rax, 0xb0(%rsp)
leaq 0xd8(%rsp), %rdi
leaq 0xb0(%rsp), %rsi
callq 0x58e40
movb %al, %cl
xorl %eax, %eax
testb $0x1, %cl
movb %al, 0x4f(%rsp)
jne 0x594f5
jmp 0x59514
leaq 0xd8(%rsp), %rdi
callq 0x5d890
movq (%rax), %rax
cmpq 0xe0(%rsp), %rax
sete %al
movb %al, 0x4f(%rsp)
movb 0x4f(%rsp), %al
testb $0x1, %al
jne 0x59521
jmp 0x596cf
movq 0x811a0(%rip), %rdi     # 0xda6c8
movq 0x110(%rsp), %rax
movw (%rax), %cx
movq 0xe0(%rsp), %rdx
movq (%rdi), %rax
movzwl %cx, %esi
callq *0xe8(%rax)
testb $0x1, %al
jne 0x5954d
jmp 0x5957d
movq 0x81174(%rip), %rax     # 0xda6c8
movq %rax, 0x40(%rsp)
leaq 0xd8(%rsp), %rdi
callq 0x58e90
movq 0x40(%rsp), %rdi
movq 0x8(%rax), %rsi
movq (%rdi), %rax
callq *0xd8(%rax)
jmp 0x59673
movq 0x81144(%rip), %rax     # 0xda6c8
movq %rax, 0x30(%rsp)
movq 0x110(%rsp), %rax
movw (%rax), %ax
movw %ax, 0x3e(%rsp)
leaq 0xd8(%rsp), %rdi
callq 0x58e90
movq 0x30(%rsp), %rdi
movq %rax, %rcx
movw 0x3e(%rsp), %ax
movq 0x8(%rcx), %rdx
movzwl %ax, %esi
callq 0x4d800
testb $0x1, %al
jne 0x595c8
jmp 0x5964a
movq 0x810f9(%rip), %rax     # 0xda6c8
movq 0x30(%rax), %rax
movq 0x50(%rax), %rax
movq %rax, 0x28(%rsp)
leaq 0xd8(%rsp), %rdi
callq 0x58e90
movq 0x28(%rsp), %rdi
movq 0x8(%rax), %rsi
callq 0x59980
leaq 0xd8(%rsp), %rdi
callq 0x58e90
movq 0x8(%rax), %rax
cmpq $0x0, 0x88(%rax)
je 0x59648
movq 0x810af(%rip), %rax     # 0xda6c8
movq 0x30(%rax), %rax
movq 0x50(%rax), %rax
movq %rax, 0x20(%rsp)
leaq 0xd8(%rsp), %rdi
callq 0x58e90
movq 0x20(%rsp), %rdi
movq 0x8(%rax), %rax
movq 0x88(%rax), %rsi
callq 0x59980
jmp 0x59671
movq 0x81077(%rip), %rax     # 0xda6c8
movq %rax, 0x18(%rsp)
leaq 0xd8(%rsp), %rdi
callq 0x58e90
movq 0x18(%rsp), %rdi
movq 0x8(%rax), %rsi
callq 0x4d960
jmp 0x59673
movq 0x8104e(%rip), %rax     # 0xda6c8
movq 0xa8(%rax), %rax
movq 0x110(%rsp), %rcx
movzwl (%rcx), %ecx
movq (%rax,%rcx,8), %rax
addq $0x58, %rax
movq %rax, 0x10(%rsp)
leaq 0xd8(%rsp), %rdi
xorl %esi, %esi
callq 0x58ef0
movq 0x10(%rsp), %rdi
movq %rax, 0xa8(%rsp)
movq 0xa8(%rsp), %rsi
callq 0x58eb0
movq %rax, 0xa0(%rsp)
jmp 0x594a3
jmp 0x596d1
jmp 0x596d5
jmp 0x59733
movq 0x80fec(%rip), %rax     # 0xda6c8
movq 0xa8(%rax), %rax
movq 0x110(%rsp), %rcx
movzwl (%rcx), %ecx
movq (%rax,%rcx,8), %rax
addq $0x88, %rax
movq %rax, 0x8(%rsp)
leaq 0xf0(%rsp), %rdi
xorl %esi, %esi
callq 0x5d8f0
movq 0x8(%rsp), %rdi
movq %rax, 0x98(%rsp)
movq 0x98(%rsp), %rsi
callq 0x5d8b0
movq %rax, 0x90(%rsp)
jmp 0x590df
movq 0x80f8e(%rip), %rax     # 0xda6c8
movq 0x30(%rax), %rax
movq 0x50(%rax), %rdi
movq (%rdi), %rax
callq *0x30(%rax)
addq $0x118, %rsp            # imm = 0x118
retq
movq 0x108(%rsp), %rdi
callq 0x8770
nopl (%rax)