// 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::Remove_barrier_for_accessing_mvpn(unsigned short, unsigned int)
inline void Address_Mapping_Unit_Page_Level::Remove_barrier_for_accessing_mvpn(stream_id_type stream_id, MVPN_type mvpn)
	{
		auto itr = domains[stream_id]->Locked_MVPNs.find(mvpn);
		if (itr == domains[stream_id]->Locked_MVPNs.end()) {
			PRINT_ERROR("Illegal operation: Unlocking an MVPN that has not been locked!");
		}
		domains[stream_id]->Locked_MVPNs.erase(itr);

		//If there are read requests waiting behind the barrier, then MQSim assumes they can be serviced with the actual page data that is accessed during GC execution
		if (domains[stream_id]->MVPN_read_transactions_waiting_behind_barrier.find(mvpn) != domains[stream_id]->MVPN_read_transactions_waiting_behind_barrier.end()) {
			domains[stream_id]->MVPN_read_transactions_waiting_behind_barrier.erase(mvpn);
			PPA_type ppn = domains[stream_id]->GlobalTranslationDirectory[mvpn].MPPN;
			if (ppn == NO_MPPN) {
				PRINT_ERROR("Reading an invalid physical flash page address in function generate_flash_read_request_for_mapping_data!")
			}

			NVM_Transaction_Flash_RD* readTR = new NVM_Transaction_Flash_RD(Transaction_Source_Type::MAPPING, stream_id,
					SECTOR_SIZE_IN_BYTE, NO_LPA, NO_PPA, NULL, mvpn, ((page_status_type)0x1) << sector_no_per_page, CurrentTimeStamp);
			Convert_ppa_to_address(ppn, readTR->Address);
			readTR->PPA = ppn;
			Stats::Total_flash_reads_for_mapping++;
			Stats::Total_flash_reads_for_mapping_per_stream[stream_id]++;

			handle_transaction_serviced_signal_from_PHY(readTR);
			
			delete readTR;
		}

		//If there are write requests waiting behind the barrier, then MQSim assumes they can be serviced with the actual page data that is accessed during GC execution. This may not be 100% true for all write requests, but, to avoid more complexity in the simulation, we accept this assumption.
		if (domains[stream_id]->MVPN_write_transaction_waiting_behind_barrier.find(mvpn) != domains[stream_id]->MVPN_write_transaction_waiting_behind_barrier.end()) {
			domains[stream_id]->MVPN_write_transaction_waiting_behind_barrier.erase(mvpn);
			//Writing back all dirty CMT entries that fall into the same translation virtual page (MVPN)
			unsigned int read_size = 0;
			page_status_type readSectorsBitmap = 0;
			LPA_type start_lpn = get_start_LPN_in_MVP(mvpn);
			LPA_type end_lpn = get_end_LPN_in_MVP(mvpn);
			for (LPA_type lpn_itr = start_lpn; lpn_itr <= end_lpn; lpn_itr++) {
				if (domains[stream_id]->CMT->Exists(stream_id, lpn_itr)) {
					if (domains[stream_id]->CMT->Is_dirty(stream_id, lpn_itr)) {
						domains[stream_id]->CMT->Make_clean(stream_id, lpn_itr);
					} else {
						page_status_type bitlocation = (((page_status_type)0x1) << (((lpn_itr - start_lpn) * GTD_entry_size) / SECTOR_SIZE_IN_BYTE));
						if ((readSectorsBitmap & bitlocation) == 0) {
							readSectorsBitmap |= bitlocation;
							read_size += SECTOR_SIZE_IN_BYTE;
						}
					}
				}
			}

			//Read the unchaged mapping entries from flash to merge them with updated parts of MVPN
			MPPN_type mppn = domains[stream_id]->GlobalTranslationDirectory[mvpn].MPPN;
			NVM_Transaction_Flash_WR* writeTR = new NVM_Transaction_Flash_WR(Transaction_Source_Type::MAPPING, stream_id, SECTOR_SIZE_IN_BYTE * sector_no_per_page,
				mvpn, mppn, NULL, mvpn, NULL, (((page_status_type)0x1) << sector_no_per_page) - 1, CurrentTimeStamp);

			Stats::Total_flash_reads_for_mapping++;
			Stats::Total_flash_writes_for_mapping++;
			Stats::Total_flash_reads_for_mapping_per_stream[stream_id]++;
			Stats::Total_flash_writes_for_mapping_per_stream[stream_id]++;

			handle_transaction_serviced_signal_from_PHY(writeTR);

			delete writeTR;
		}
	}

// Assembly:
pushq %rbp
pushq %r15
pushq %r14
pushq %r13
pushq %r12
pushq %rbx
subq $0x18, %rsp
movl %esi, %r14d
movq %rdi, %rbx
leaq 0xc(%rsp), %rsi
movl %edx, (%rsi)
movq 0xa8(%rdi), %rax
leal (,%r14,8), %r15d
movl $0x118, %edi            # imm = 0x118
addq (%rax,%r15), %rdi
callq 0x28510
movq 0xa8(%rbx), %rcx
movq (%rcx,%r15), %rdi
leaq 0x120(%rdi), %rcx
cmpq %rcx, %rax
je 0x26f63
movl %r14d, %r13d
addq $0x118, %rdi            # imm = 0x118
movq %rax, %rsi
callq 0x2779e
movq 0xa8(%rbx), %rax
leal (,%r13,8), %r15d
movl $0x1a8, %edi            # imm = 0x1A8
addq (%rax,%r15), %rdi
leaq 0xc(%rsp), %rsi
callq 0x28510
movq 0xa8(%rbx), %rcx
movq (%rcx,%r15), %rdi
leaq 0x1b0(%rdi), %rcx
movzwl %r14w, %ebp
cmpq %rcx, %rax
je 0x26df4
addq $0x1a8, %rdi            # imm = 0x1A8
leaq 0xc(%rsp), %r14
movq %r14, %rsi
callq 0x27358
movq 0xa8(%rbx), %rax
movq (%rax,%r13,8), %rax
movq (%rax), %rax
movl (%r14), %ecx
movq %rcx, 0x10(%rsp)
shlq $0x4, %rcx
movl (%rax,%rcx), %r15d
movl $0xffffffff, %eax       # imm = 0xFFFFFFFF
cmpq %rax, %r15
je 0x26f82
movl $0xa0, %edi
callq 0x7370
movq %rax, %r14
movb 0x7c(%rbx), %cl
pushq $0x1
popq %r12
shlq %cl, %r12
callq 0x1f784
movq %rax, %rdi
callq 0x1fafc
pushq $0x3
popq %rsi
pushq $-0x1
popq %r8
movq %r14, %rdi
movl %ebp, %edx
movl $0x200, %ecx            # imm = 0x200
movq %r8, %r9
pushq %rax
pushq %r12
pushq 0x20(%rsp)
pushq $0x0
callq 0x3a21a
addq $0x20, %rsp
movq %r14, %rdx
addq $0x38, %rdx
movq (%rbx), %rax
movq %rbx, %rdi
movq %r15, %rsi
callq *0x88(%rax)
movq %r15, 0x60(%r14)
leaq 0x3b92d(%rip), %rax     # 0x626f0
incq (%rax)
leal (,%r13,8), %r15d
leaq 0x3b92b(%rip), %rax     # 0x62700
incq (%rax,%r15)
movq %r14, %rdi
callq 0x26100
movq %r14, %rdi
callq 0x7340
movq 0xa8(%rbx), %rax
movq (%rax,%r15), %rdi
addq $0x1d8, %rdi            # imm = 0x1D8
leaq 0xc(%rsp), %rsi
callq 0x28510
movq 0xa8(%rbx), %rcx
movq (%rcx,%r13,8), %rdi
leaq 0x1e0(%rdi), %rcx
cmpq %rcx, %rax
je 0x26f54
pushq $-0x1
popq %r12
addq $0x1d8, %rdi            # imm = 0x1D8
leaq 0xc(%rsp), %r14
movq %r14, %rsi
callq 0x27358
movl (%r14), %r15d
movl 0xc0(%rbx), %eax
movl %eax, %r14d
imull %r15d, %r14d
incl %r15d
imull %eax, %r15d
decl %r15d
movq 0xa8(%rbx), %rax
movq (%rax,%r13,8), %rax
cmpq %r15, %r14
ja 0x26eaf
movq 0x10(%rax), %rdi
movl %ebp, %esi
movq %r14, %rdx
callq 0x264a2
testb %al, %al
je 0x26eaa
movq 0xa8(%rbx), %rax
movq (%rax,%r13,8), %rax
movq 0x10(%rax), %rdi
movl %ebp, %esi
movq %r14, %rdx
callq 0x20e12
testb %al, %al
je 0x26eaa
movq 0xa8(%rbx), %rax
movq (%rax,%r13,8), %rax
movq 0x10(%rax), %rdi
movl %ebp, %esi
movq %r14, %rdx
callq 0x20e82
incq %r14
jmp 0x26e52
movq (%rax), %rax
movl 0xc(%rsp), %r15d
movq %r15, %rcx
shlq $0x4, %rcx
movl (%rax,%rcx), %eax
movq %rax, 0x10(%rsp)
movl $0xb0, %edi
callq 0x7370
movq %rax, %r14
movl 0x7c(%rbx), %ebx
movl %ebx, %ecx
shlq %cl, %r12
callq 0x1f784
movq %rax, %rdi
callq 0x1fafc
shll $0x9, %ebx
notq %r12
subq $0x8, %rsp
pushq $0x3
popq %rsi
movq %r14, %rdi
movl %ebp, %edx
movl %ebx, %ecx
movq %r15, %r8
movq 0x18(%rsp), %r9
pushq %rax
pushq %r12
pushq $0x0
pushq %r15
pushq $0x0
callq 0x3a2c6
addq $0x30, %rsp
leaq 0x3b7d3(%rip), %rax     # 0x626f0
incq (%rax)
leaq 0x3b7d1(%rip), %rax     # 0x626f8
incq (%rax)
shll $0x3, %r13d
leaq 0x3b7cb(%rip), %rax     # 0x62700
incq (%rax,%r13)
leaq 0x3bfc0(%rip), %rax     # 0x62f00
incq (%rax,%r13)
movq %r14, %rdi
callq 0x26100
movq %r14, %rdi
callq 0x7340
addq $0x18, %rsp
popq %rbx
popq %r12
popq %r13
popq %r14
popq %r15
popq %rbp
retq
movq 0x3b086(%rip), %rbx     # 0x61ff0
leaq 0x1d617(%rip), %rsi     # 0x44588
movq %rbx, %rdi
callq 0x7360
leaq 0x1fd62(%rip), %rsi     # 0x46ce2
jmp 0x26f9f
movq 0x3b067(%rip), %rbx     # 0x61ff0
leaq 0x1d5f8(%rip), %rsi     # 0x44588
movq %rbx, %rdi
callq 0x7360
leaq 0x1fb4c(%rip), %rsi     # 0x46aeb
movq %rbx, %rdi
callq 0x7360
movq %rax, %rdi
callq 0x71a0
movq 0x3b01a(%rip), %rdi     # 0x61fd0
callq 0x73d0
pushq $0x1
popq %rdi
callq 0x73e0
jmp 0x26fc5
movq %rax, %rbx
movq %r14, %rdi
callq 0x7340
movq %rbx, %rdi
callq 0x75d0