// File: /workspace/github_cpp_makefile_star2_O3/CMU-SAFARI[P]MQSim/src/host/IO_Flow_Base.cpp
// Function: Host_Components::IO_Flow_Base::NVMe_consume_io_request(Completion_Queue_Entry*)
void IO_Flow_Base::NVMe_consume_io_request(Completion_Queue_Entry* cqe)
	{
		//Find the request and update statistics
		Host_IO_Request* request = nvme_software_request_queue[cqe->Command_Identifier];
		nvme_software_request_queue.erase(cqe->Command_Identifier);
		available_command_ids.insert(cqe->Command_Identifier);
		sim_time_type device_response_time = Simulator->Time() - request->Enqueue_time;
		sim_time_type request_delay = Simulator->Time() - request->Arrival_time;
		STAT_serviced_request_count++;
		STAT_serviced_request_count_short_term++;

		STAT_sum_device_response_time += device_response_time;
		STAT_sum_device_response_time_short_term += device_response_time;
		STAT_sum_request_delay += request_delay;
		STAT_sum_request_delay_short_term += request_delay;
		if (device_response_time > STAT_max_device_response_time) {
			STAT_max_device_response_time = device_response_time;
		}
		if (device_response_time < STAT_min_device_response_time) {
			STAT_min_device_response_time = device_response_time;
		}
		if (request_delay > STAT_max_request_delay) {
			STAT_max_request_delay = request_delay;
		}
		if (request_delay < STAT_min_request_delay) {
			STAT_min_request_delay = request_delay;
		}
		STAT_transferred_bytes_total += request->LBA_count * SECTOR_SIZE_IN_BYTE;
		
		if (request->Type == Host_IO_Request_Type::READ) {
			STAT_serviced_read_request_count++;
			STAT_sum_device_response_time_read += device_response_time;
			STAT_sum_request_delay_read += request_delay;
			if (device_response_time > STAT_max_device_response_time_read) {
				STAT_max_device_response_time_read = device_response_time;
			}
			if (device_response_time < STAT_min_device_response_time_read) {
				STAT_min_device_response_time_read = device_response_time;
			}
			if (request_delay > STAT_max_request_delay_read) {
				STAT_max_request_delay_read = request_delay;
			}
			if (request_delay < STAT_min_request_delay_read) {
				STAT_min_request_delay_read = request_delay;
			}
			STAT_transferred_bytes_read += request->LBA_count * SECTOR_SIZE_IN_BYTE;
		} else {
			STAT_serviced_write_request_count++;
			STAT_sum_device_response_time_write += device_response_time;
			STAT_sum_request_delay_write += request_delay;
			if (device_response_time > STAT_max_device_response_time_write) {
				STAT_max_device_response_time_write = device_response_time;
			}
			if (device_response_time < STAT_min_device_response_time_write) {
				STAT_min_device_response_time_write = device_response_time;
			}
			if (request_delay > STAT_max_request_delay_write) {
				STAT_max_request_delay_write = request_delay;
			}
			if (request_delay < STAT_min_request_delay_write) {
				STAT_min_request_delay_write = request_delay;
			}
			STAT_transferred_bytes_write += request->LBA_count * SECTOR_SIZE_IN_BYTE;
		}

		delete request;

		nvme_queue_pair.Submission_queue_head = cqe->SQ_Head;
		
		//MQSim always assumes that the request is processed correctly, so no need to check cqe->SF_P

		//If the submission queue is not full anymore, then enqueue waiting requests
		while(waiting_requests.size() > 0) {
			if (!NVME_SQ_FULL(nvme_queue_pair) && available_command_ids.size() > 0) {
				Host_IO_Request* new_req = waiting_requests.front();
				waiting_requests.pop_front();
				if (nvme_software_request_queue[*available_command_ids.begin()] != NULL) {
					PRINT_ERROR("Unexpteced situation in IO_Flow_Base! Overwriting a waiting I/O request in the queue!")
				} else {
					new_req->IO_queue_info = *available_command_ids.begin();
					nvme_software_request_queue[*available_command_ids.begin()] = new_req;
					available_command_ids.erase(available_command_ids.begin());
					request_queue_in_memory[nvme_queue_pair.Submission_queue_tail] = new_req;
					NVME_UPDATE_SQ_TAIL(nvme_queue_pair);
				}
				new_req->Enqueue_time = Simulator->Time();
				pcie_root_complex->Write_to_device(nvme_queue_pair.Submission_tail_register_address_on_device, nvme_queue_pair.Submission_queue_tail);//Based on NVMe protocol definition, the updated tail pointer should be informed to the device
			} else {
				break;
			}
		}

		delete cqe;

		//Announce simulation progress
		if (stop_time > 0) {
			progress = int(Simulator->Time() / (double)stop_time * 100);
		} else {
			progress = int(STAT_serviced_request_count / (double)total_requests_to_be_generated * 100);
		}

		if (progress >= next_progress_step) {
			std::string progress_bar;
			int barWidth = 100;
			progress_bar += "[";
			int pos = progress;
			for (int i = 0; i < barWidth; i += 5) {
				if (i < pos) {
					progress_bar += "=";
				} else if (i == pos) {
					progress_bar += ">";
				} else {
					progress_bar += " ";
				}
			}
			progress_bar += "] ";
			PRINT_MESSAGE(progress_bar << " " << progress << "% progress in " << ID() << std::endl)
			next_progress_step += 5;
		}

		if (Simulator->Time() > next_logging_milestone) {
			log_file << Simulator->Time() / SIM_TIME_TO_MICROSECONDS_COEFF << "\t" << Get_device_response_time_short_term() << "\t" << Get_end_to_end_request_delay_short_term() << std::endl;
			STAT_sum_device_response_time_short_term = 0;
			STAT_sum_request_delay_short_term = 0;
			STAT_serviced_request_count_short_term = 0;
			next_logging_milestone = Simulator->Time() + logging_period;
		}
	}

// Assembly:
pushq %rbp
pushq %r15
pushq %r14
pushq %r13
pushq %r12
pushq %rbx
subq $0x48, %rsp
movq %rsi, %r14
movq %rdi, %rbx
leaq 0x118(%rdi), %r15
leaq 0xc(%rsi), %rbp
movzwl 0xc(%rsi), %eax
movq %rsp, %r12
movq %rax, (%r12)
movq %r15, %rdi
movq %r12, %rsi
callq 0x21920
movq (%rax), %r13
movq %r14, 0x20(%rsp)
movzwl 0xc(%r14), %eax
movq %rax, (%r12)
movq %rsp, %rsi
movq %r15, %rdi
callq 0x21bc2
leaq 0xb8(%rbx), %r12
movq %r12, %rdi
movq %rbp, %rsi
callq 0x216d2
callq 0x28018
movq %rax, %rdi
callq 0x2841a
movq %rax, %rbp
subq 0x8(%r13), %rbp
callq 0x28018
movq %rax, %rdi
callq 0x2841a
subq (%r13), %rax
incl 0x160(%rbx)
incl 0x468(%rbx)
addq %rbp, 0x170(%rbx)
addq %rbp, 0x458(%rbx)
addq %rax, 0x1b8(%rbx)
addq %rax, 0x460(%rbx)
cmpq 0x1a0(%rbx), %rbp
jbe 0x1efca
movq %rbp, 0x1a0(%rbx)
cmpq 0x188(%rbx), %rbp
jae 0x1efda
movq %rbp, 0x188(%rbx)
cmpq 0x1e8(%rbx), %rax
jbe 0x1efea
movq %rax, 0x1e8(%rbx)
cmpq 0x1d0(%rbx), %rax
jae 0x1effa
movq %rax, 0x1d0(%rbx)
movl 0x18(%r13), %ecx
shll $0x9, %ecx
addq %rcx, 0x200(%rbx)
cmpl $0x0, 0x1c(%r13)
je 0x1f06a
incl 0x168(%rbx)
addq %rbp, 0x180(%rbx)
addq %rax, 0x1c8(%rbx)
cmpq 0x1b0(%rbx), %rbp
jbe 0x1f033
movq %rbp, 0x1b0(%rbx)
cmpq 0x198(%rbx), %rbp
jae 0x1f043
movq %rbp, 0x198(%rbx)
cmpq 0x1f8(%rbx), %rax
jbe 0x1f053
movq %rax, 0x1f8(%rbx)
movl $0x210, %edx            # imm = 0x210
cmpq 0x1e0(%rbx), %rax
jae 0x1f0c6
leaq 0x1e0(%rbx), %rsi
jmp 0x1f0c3
incl 0x164(%rbx)
addq %rbp, 0x178(%rbx)
addq %rax, 0x1c0(%rbx)
cmpq 0x1a8(%rbx), %rbp
jbe 0x1f08e
movq %rbp, 0x1a8(%rbx)
cmpq 0x190(%rbx), %rbp
jae 0x1f09e
movq %rbp, 0x190(%rbx)
cmpq 0x1f0(%rbx), %rax
jbe 0x1f0ae
movq %rax, 0x1f0(%rbx)
movl $0x208, %edx            # imm = 0x208
cmpq 0x1d8(%rbx), %rax
jae 0x1f0c6
leaq 0x1d8(%rbx), %rsi
movq %rax, (%rsi)
addq %rcx, (%rbx,%rdx)
movq %r13, %rdi
callq 0x7370
movq 0x20(%rsp), %rax
movzwl 0x8(%rax), %eax
movw %ax, 0x80(%rbx)
movq 0x110(%rbx), %rax
testq %rax, %rax
je 0x1f213
movq %rsp, %r13
movzwl 0x82(%rbx), %ecx
movzwl 0x84(%rbx), %edx
decl %edx
cmpl %ecx, %edx
jle 0x1f11b
incl %ecx
movzwl 0x80(%rbx), %edx
cmpl %edx, %ecx
jne 0x1f129
jmp 0x1f213
cmpw $0x0, 0x80(%rbx)
je 0x1f213
cmpq $0x0, 0xe0(%rbx)
je 0x1f213
movq 0x100(%rbx), %rbp
movq 0x10(%rbp), %r14
decq %rax
movq %rax, 0x110(%rbx)
movq %rbp, %rdi
callq 0x7580
movq %rbp, %rdi
callq 0x7370
movq 0xd0(%rbx), %rax
movzwl 0x20(%rax), %eax
movq %rax, (%rsp)
movq %r15, %rdi
movq %r13, %rsi
callq 0x21920
cmpq $0x0, (%rax)
jne 0x1f56b
movq 0xd0(%rbx), %rax
movzwl 0x20(%rax), %eax
movw %ax, 0x20(%r14)
movq %rax, (%rsp)
movq %r15, %rdi
movq %r13, %rsi
callq 0x21920
movq %r14, (%rax)
movq 0xd0(%rbx), %rsi
movq %r12, %rdi
callq 0x21cac
movzwl 0x82(%rbx), %eax
movq 0xe8(%rbx), %rcx
movq %r14, (%rcx,%rax,8)
incl %eax
cmpw 0x84(%rbx), %ax
movl $0x0, %ecx
cmovel %ecx, %eax
movw %ax, 0x82(%rbx)
callq 0x28018
movq %rax, %rdi
callq 0x2841a
movq %rax, 0x8(%r14)
movq 0x58(%rbx), %rdi
movq 0x88(%rbx), %rsi
movzwl 0x82(%rbx), %edx
callq 0x24e5a
movq 0x110(%rbx), %rax
testq %rax, %rax
jne 0x1f0f5
movq 0x20(%rsp), %rdi
callq 0x7370
cmpq $0x0, 0x48(%rbx)
je 0x1f279
callq 0x28018
movq %rax, %rdi
callq 0x2841a
movq %rax, %xmm1
movq 0x38682(%rip), %xmm2    # 0x578c0
punpckldq %xmm2, %xmm1    # xmm1 = xmm1[0],xmm2[0],xmm1[1],xmm2[1]
movapd 0x38686(%rip), %xmm3    # 0x578d0
subpd %xmm3, %xmm1
movapd %xmm1, %xmm0
unpckhpd %xmm1, %xmm0            # xmm0 = xmm0[1],xmm1[1]
addsd %xmm1, %xmm0
movq 0x48(%rbx), %xmm1
punpckldq %xmm2, %xmm1    # xmm1 = xmm1[0],xmm2[0],xmm1[1],xmm2[1]
subpd %xmm3, %xmm1
movapd %xmm1, %xmm2
unpckhpd %xmm1, %xmm2            # xmm2 = xmm2[1],xmm1[1]
addsd %xmm1, %xmm2
divsd %xmm2, %xmm0
jmp 0x1f290
movl 0x160(%rbx), %eax
cvtsi2sd %rax, %xmm0
movl 0x50(%rbx), %eax
cvtsi2sd %rax, %xmm1
divsd %xmm1, %xmm0
mulsd 0x37c08(%rip), %xmm0    # 0x56ea0
cvttsd2si %xmm0, %eax
movl %eax, 0x218(%rbx)
cmpl %eax, 0x21c(%rbx)
jg 0x1f423
leaq 0x10(%rsp), %rax
movq %rax, -0x10(%rax)
movq $0x0, -0x8(%rax)
movb $0x0, (%rax)
leaq 0x38725(%rip), %rsi     # 0x579ee
movq %rsp, %rdi
callq 0x7690
movl 0x218(%rbx), %ebp
xorl %r13d, %r13d
leaq 0x38b0d(%rip), %r15     # 0x57dee
leaq 0x36363(%rip), %r12     # 0x5564b
movq %rsp, %r14
cmpl %r13d, %ebp
movq %r15, %rsi
leaq 0x362fc(%rip), %rax     # 0x555f4
cmoveq %rax, %rsi
cmovgq %r12, %rsi
movq %r14, %rdi
callq 0x7690
leal 0x5(%r13), %eax
cmpl $0x5f, %r13d
movl %eax, %r13d
jb 0x1f2eb
leaq 0x386d4(%rip), %rsi     # 0x579f0
movq %rsp, %rdi
callq 0x7690
movq (%rsp), %rsi
movq 0x8(%rsp), %rdx
movq 0x4fc54(%rip), %rdi     # 0x6ef88
callq 0x7400
movq %rax, %r14
leaq 0x38aab(%rip), %rsi     # 0x57dee
movl $0x1, %edx
movq %rax, %rdi
callq 0x7400
movl 0x218(%rbx), %esi
movq %r14, %rdi
callq 0x75f0
movq %rax, %r14
leaq 0x3868b(%rip), %rsi     # 0x579f3
movl $0xe, %edx
movq %rax, %rdi
callq 0x7400
leaq 0x38(%rsp), %r12
movq %r12, -0x10(%r12)
movq 0x8(%rbx), %rsi
movq 0x10(%rbx), %rdx
addq %rsi, %rdx
leaq 0x28(%rsp), %rdi
callq 0xaf32
movq 0x28(%rsp), %rsi
movq 0x30(%rsp), %rdx
movq %r14, %rdi
callq 0x7400
movq %rax, %r14
movq (%rax), %rax
movq -0x18(%rax), %rdi
addq %r14, %rdi
movl $0xa, %esi
callq 0x7380
movsbl %al, %esi
movq %r14, %rdi
callq 0x7040
movq %rax, %rdi
callq 0x7290
movq %rax, %r14
movq (%rax), %rax
movq -0x18(%rax), %rdi
addq %r14, %rdi
movl $0xa, %esi
callq 0x7380
movsbl %al, %esi
movq %r14, %rdi
callq 0x7040
movq %rax, %rdi
callq 0x7290
movq 0x28(%rsp), %rdi
cmpq %r12, %rdi
je 0x1f409
callq 0x7370
addl $0x5, 0x21c(%rbx)
movq (%rsp), %rdi
leaq 0x10(%rsp), %rax
cmpq %rax, %rdi
je 0x1f423
callq 0x7370
callq 0x28018
movq %rax, %rdi
callq 0x2841a
cmpq 0x230(%rbx), %rax
jbe 0x1f55c
leaq 0x458(%rbx), %r15
leaq 0x258(%rbx), %r14
callq 0x28018
movq %rax, %rdi
callq 0x2841a
shrq $0x3, %rax
movabsq $0x20c49ba5e353f7cf, %r12 # imm = 0x20C49BA5E353F7CF
mulq %r12
shrq $0x4, %rdx
movq %r14, %rdi
movq %rdx, %rsi
callq 0x7280
movq %rax, %r14
leaq 0x38558(%rip), %rsi     # 0x579da
movl $0x1, %edx
movq %rax, %rdi
callq 0x7400
movl 0x468(%rbx), %ecx
testq %rcx, %rcx
je 0x1f4b1
movq (%r15), %rax
xorl %edx, %edx
divq %rcx
shrq $0x3, %rax
mulq %r12
shrq $0x4, %rdx
movl %edx, %esi
jmp 0x1f4b3
xorl %esi, %esi
movq %r14, %rdi
callq 0x7280
movq %rax, %r14
leaq 0x38515(%rip), %rsi     # 0x579da
movl $0x1, %edx
movq %rax, %rdi
callq 0x7400
cmpl $0x0, 0x160(%rbx)
je 0x1f4fc
movq 0x460(%rbx), %rax
movl 0x468(%rbx), %ecx
xorl %edx, %edx
divq %rcx
shrq $0x3, %rax
mulq %r12
shrq $0x4, %rdx
movl %edx, %esi
jmp 0x1f4fe
xorl %esi, %esi
movq %r14, %rdi
callq 0x7280
movq %rax, %r14
movq (%rax), %rax
movq -0x18(%rax), %rdi
addq %r14, %rdi
movl $0xa, %esi
callq 0x7380
movsbl %al, %esi
movq %r14, %rdi
callq 0x7040
movq %rax, %rdi
callq 0x7290
xorpd %xmm0, %xmm0
movupd %xmm0, (%r15)
movl $0x0, 0x10(%r15)
callq 0x28018
movq %rax, %rdi
callq 0x2841a
addq 0x228(%rbx), %rax
movq %rax, 0x230(%rbx)
addq $0x48, %rsp
popq %rbx
popq %r12
popq %r13
popq %r14
popq %r15
popq %rbp
retq
movq 0x4fa7e(%rip), %rbx     # 0x6eff0
leaq 0x3702f(%rip), %rsi     # 0x565a8
movq %rbx, %rdi
callq 0x7390
leaq 0x3847a(%rip), %rsi     # 0x57a02
movq %rbx, %rdi
callq 0x7390
movq %rax, %rdi
callq 0x71c0
movq 0x4fa31(%rip), %rdi     # 0x6efd0
callq 0x7430
movl $0x1, %edi
callq 0x7440
jmp 0x1f5c8
jmp 0x1f5c8
jmp 0x1f5c8
movq %rax, %rbx
movq 0x28(%rsp), %rdi
cmpq %r12, %rdi
je 0x1f5cb
callq 0x7370
jmp 0x1f5cb
movq %rax, %rbx
movq (%rsp), %rdi
leaq 0x10(%rsp), %rax
cmpq %rax, %rdi
je 0x1f5de
callq 0x7370
movq %rbx, %rdi
callq 0x7620