// File: /workspace/github_cpp_makefile_star2_O1/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, %ebp
movq %rdi, %rbx
movl %edx, 0xc(%rsp)
movq 0xa8(%rdi), %rax
movl %esi, %r13d
movq (%rax,%r13,8), %rdi
movq 0x128(%rdi), %rsi
leaq 0x120(%rdi), %rax
movq %rax, %rcx
testq %rsi, %rsi
je 0x30786
movq %rax, %rcx
xorl %r8d, %r8d
cmpl %edx, 0x20(%rsi)
setb %r8b
cmovaeq %rsi, %rcx
movq 0x10(%rsi,%r8,8), %rsi
testq %rsi, %rsi
jne 0x3076e
movq %rax, %rsi
cmpq %rax, %rcx
je 0x30798
cmpl %edx, 0x20(%rcx)
cmovaq %rax, %rcx
movq %rcx, %rsi
cmpq %rax, %rsi
je 0x30b29
addq $0x118, %rdi            # imm = 0x118
callq 0x31098
movq 0xa8(%rbx), %rax
movq (%rax,%r13,8), %r14
movq 0x1b8(%r14), %rdx
leaq 0x1b0(%r14), %rax
movq %rax, %rcx
testq %rdx, %rdx
je 0x307ec
movl 0xc(%rsp), %esi
movq %rax, %rcx
xorl %edi, %edi
cmpl %esi, 0x20(%rdx)
setb %dil
cmovaeq %rdx, %rcx
movq 0x10(%rdx,%rdi,8), %rdx
testq %rdx, %rdx
jne 0x307d5
movq %rax, %rdx
cmpq %rax, %rcx
je 0x30802
movl 0xc(%rsp), %edx
cmpl 0x20(%rcx), %edx
cmovbq %rax, %rcx
movq %rcx, %rdx
movzwl %bp, %ebp
cmpq %rax, %rdx
je 0x308f4
movl %ebp, 0x10(%rsp)
addq $0x1a8, %r14            # imm = 0x1A8
leaq 0xc(%rsp), %r15
movq %r14, %rdi
movq %r15, %rsi
callq 0x30e00
movq %r14, %rdi
movq %rax, %rsi
callq 0x30e78
movq 0xa8(%rbx), %rax
movq (%rax,%r13,8), %rax
movq (%rax), %rax
movl (%r15), %r12d
movq %r12, %rcx
shlq $0x4, %rcx
movl (%rax,%rcx), %r15d
movl $0xffffffff, %eax       # imm = 0xFFFFFFFF
cmpq %rax, %r15
je 0x30b48
movl $0xa0, %edi
callq 0x73a0
movq %rax, %r14
movb 0x7c(%rbx), %cl
movl $0x1, %ebp
shlq %cl, %rbp
callq 0x281b4
movq %rax, %rdi
callq 0x285a6
movq %r14, %rdi
movl $0x3, %esi
movl 0x10(%rsp), %edx
movl $0x200, %ecx            # imm = 0x200
movq $-0x1, %r8
movq $-0x1, %r9
pushq %rax
pushq %rbp
pushq %r12
pushq $0x0
callq 0x48b70
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 0x3ee4e(%rip), %rax     # 0x6f720
incq (%rax)
leaq 0x3ee54(%rip), %rax     # 0x6f730
incq (%rax,%r13,8)
movq %r14, %rdi
callq 0x2f856
movq %r14, %rdi
callq 0x7370
movl 0x10(%rsp), %ebp
movq 0xa8(%rbx), %rax
movq (%rax,%r13,8), %r14
movq 0x1e8(%r14), %rdx
leaq 0x1e0(%r14), %rax
movq %rax, %rcx
testq %rdx, %rdx
je 0x30933
movl 0xc(%rsp), %esi
movq %rax, %rcx
xorl %edi, %edi
cmpl %esi, 0x20(%rdx)
setb %dil
cmovaeq %rdx, %rcx
movq 0x10(%rdx,%rdi,8), %rdx
testq %rdx, %rdx
jne 0x3091c
movq %rax, %rdx
cmpq %rax, %rcx
je 0x30949
movl 0xc(%rsp), %edx
cmpl 0x20(%rcx), %edx
cmovbq %rax, %rcx
movq %rcx, %rdx
cmpq %rax, %rdx
je 0x30b1a
addq $0x1d8, %r14            # imm = 0x1D8
leaq 0xc(%rsp), %r15
movq %r14, %rdi
movq %r15, %rsi
callq 0x30e00
movq %r14, %rdi
movq %rax, %rsi
callq 0x30e78
movl (%r15), %ecx
movl 0xc0(%rbx), %edx
movl %edx, %eax
imull %ecx, %eax
incl %ecx
imull %edx, %ecx
decl %ecx
cmpl %ecx, %eax
ja 0x30a5e
movl %ecx, %r15d
movl %eax, %r14d
movq %r13, %r12
shlq $0x38, %r12
movq 0xa8(%rbx), %rax
movq (%rax,%r13,8), %rax
movq 0x10(%rax), %rdi
movq %r14, %rcx
orq %r12, %rcx
movq (%rdi), %r8
movq 0x8(%rdi), %r9
movq %rcx, %rax
xorl %edx, %edx
divq %r9
movq %rdx, %rsi
movq (%r8,%rdx,8), %rdx
movl $0x0, %eax
testq %rdx, %rdx
je 0x30a0c
movq (%rdx), %r10
movq %rdx, %rax
cmpq 0x8(%r10), %rcx
je 0x30a0c
movq %r10, %r11
movq (%r10), %r10
testq %r10, %r10
je 0x30a0a
movq 0x8(%r10), %r8
movq %r8, %rax
xorl %edx, %edx
divq %r9
movl $0x0, %eax
cmpq %rsi, %rdx
jne 0x30a0c
movq %r11, %rax
cmpq %r8, %rcx
jne 0x309df
jmp 0x30a0c
xorl %eax, %eax
testq %rax, %rax
je 0x30a16
movq (%rax), %rax
jmp 0x30a18
xorl %eax, %eax
testq %rax, %rax
je 0x30a4e
movq 0x10(%rax), %rax
cmpl $0x2, 0x14(%rax)
jne 0x30a4e
movl %ebp, %esi
movq %r14, %rdx
callq 0x29bd2
testb %al, %al
je 0x30a4e
movq 0xa8(%rbx), %rax
movq (%rax,%r13,8), %rax
movq 0x10(%rax), %rdi
movl %ebp, %esi
movq %r14, %rdx
callq 0x29c9c
leaq 0x1(%r14), %rax
cmpq %r15, %r14
movq %rax, %r14
jne 0x3099e
movq 0xa8(%rbx), %rax
movq (%rax,%r13,8), %rax
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 0x73a0
movq %rax, %r14
movl 0x7c(%rbx), %ebx
movq $-0x1, %r12
movl %ebx, %ecx
shlq %cl, %r12
callq 0x281b4
movq %rax, %rdi
callq 0x285a6
shll $0x9, %ebx
notq %r12
subq $0x8, %rsp
xorl %r10d, %r10d
movq %r14, %rdi
movl $0x3, %esi
movl %ebp, %edx
movl %ebx, %ecx
movq %r15, %r8
movq 0x18(%rsp), %r9
pushq %rax
pushq %r12
pushq %r10
pushq %r15
pushq %r10
callq 0x48c24
addq $0x30, %rsp
leaq 0x3ec3d(%rip), %rax     # 0x6f720
incq (%rax)
leaq 0x3ec3b(%rip), %rax     # 0x6f728
incq (%rax)
shll $0x3, %r13d
leaq 0x3ec35(%rip), %rax     # 0x6f730
incq (%rax,%r13)
leaq 0x3f42a(%rip), %rax     # 0x6ff30
incq (%rax,%r13)
movq %r14, %rdi
callq 0x2f856
movq %r14, %rdi
callq 0x7370
addq $0x18, %rsp
popq %rbx
popq %r12
popq %r13
popq %r14
popq %r15
popq %rbp
retq
movq 0x3e4c0(%rip), %rbx     # 0x6eff0
leaq 0x25a71(%rip), %rsi     # 0x565a8
movq %rbx, %rdi
callq 0x7390
leaq 0x282cc(%rip), %rsi     # 0x58e12
jmp 0x30b65
movq 0x3e4a1(%rip), %rbx     # 0x6eff0
leaq 0x25a52(%rip), %rsi     # 0x565a8
movq %rbx, %rdi
callq 0x7390
leaq 0x280b6(%rip), %rsi     # 0x58c1b
movq %rbx, %rdi
callq 0x7390
movq %rax, %rdi
callq 0x71c0
movq 0x3e454(%rip), %rdi     # 0x6efd0
callq 0x7430
movl $0x1, %edi
callq 0x7440
jmp 0x30b8d
movq %rax, %rbx
movq %r14, %rdi
callq 0x7370
movq %rbx, %rdi
callq 0x7620