// File: CMU-SAFARI[P]MQSim/src/host/SATA_HBA.cpp
// Function: Host_Components::SATA_HBA::Execute_simulator_event(MQSimEngine::Sim_Event*)
void SATA_HBA::Execute_simulator_event(MQSimEngine::Sim_Event* event)
	{
		switch ((HBA_Sim_Events)event->Type)
		{
			case HBA_Sim_Events::CONSUME_IO_REQUEST:
			{
				Completion_Queue_Entry* cqe = consume_requests.front();
				consume_requests.pop();
				//Find the request and update statistics
				Host_IO_Request* request = sata_ncq.queue[cqe->Command_Identifier];
				sata_ncq.queue.erase(cqe->Command_Identifier);
				available_command_ids.insert(cqe->Command_Identifier);
				sata_ncq.Submission_queue_head = cqe->SQ_Head;

				((*IO_flows)[request->Source_flow_id])->SATA_consume_io_request(request);

				Update_and_submit_ncq_completion_info();

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

				delete cqe;

				if(consume_requests.size() > 0) {
					Simulator->Register_sim_event(Simulator->Time() + hba_processing_delay, this, NULL, static_cast<int>(HBA_Sim_Events::CONSUME_IO_REQUEST));
				}
				break;
			}
			case HBA_Sim_Events::SUBMIT_IO_REQUEST:
			{
				Host_IO_Request* request = host_requests.front();
				host_requests.pop();

				//If the hardware queue is full
				if (SATA_SQ_FULL(sata_ncq) || available_command_ids.size() == 0) {
					waiting_requests_for_submission.push_back(request);
				} else {
					if (sata_ncq.queue[*available_command_ids.begin()] != NULL) {
						PRINT_ERROR("Unexpteced situation in IO_Flow_Base! Overwriting an unhandled I/O request in the queue!")
					} else {
						request->IO_queue_info = *available_command_ids.begin();
						sata_ncq.queue[*available_command_ids.begin()] = request;
						available_command_ids.erase(available_command_ids.begin());
						request_queue_in_memory[sata_ncq.Submission_queue_tail] = request;
						SATA_UPDATE_SQ_TAIL(sata_ncq);
					}
					request->Enqueue_time = Simulator->Time();
					pcie_root_complex->Write_to_device(sata_ncq.Submission_tail_register_address_on_device, sata_ncq.Submission_queue_tail);//Based on NVMe protocol definition, the updated tail pointer should be informed to the device
				}

				if (host_requests.size() > 0) {
					Simulator->Register_sim_event(Simulator->Time() + hba_processing_delay, this, NULL, static_cast<int>(HBA_Sim_Events::SUBMIT_IO_REQUEST));
				}

				break;
			}
		} //switch ((HBA_Sim_Events)event->Type)
	}

// Assembly:
subq $0x138, %rsp            # imm = 0x138
movq %rdi, 0x130(%rsp)
movq %rsi, 0x128(%rsp)
movq 0x130(%rsp), %rax
movq %rax, 0x68(%rsp)
movq 0x128(%rsp), %rax
movl 0x18(%rax), %eax
movl %eax, 0x74(%rsp)
testl %eax, %eax
je 0x40262
jmp 0x3fe1d
movl 0x74(%rsp), %eax
subl $0x1, %eax
jne 0x40554
jmp 0x3fe2c
movq 0x68(%rsp), %rdi
addq $0x110, %rdi            # imm = 0x110
callq 0x409a0
movq 0x68(%rsp), %rdi
movq (%rax), %rax
movq %rax, 0x120(%rsp)
addq $0x110, %rdi            # imm = 0x110
callq 0x409b0
movq 0x68(%rsp), %rdi
addq $0x48, %rdi
addq $0x30, %rdi
movq 0x120(%rsp), %rax
movzwl 0xc(%rax), %eax
movq %rax, 0x110(%rsp)
leaq 0x110(%rsp), %rsi
callq 0x34310
movq 0x68(%rsp), %rdi
movq (%rax), %rax
movq %rax, 0x118(%rsp)
addq $0x48, %rdi
addq $0x30, %rdi
movq 0x120(%rsp), %rax
movzwl 0xc(%rax), %eax
movq %rax, 0x108(%rsp)
leaq 0x108(%rsp), %rsi
callq 0x34340
movq 0x68(%rsp), %rdi
addq $0xb0, %rdi
movq 0x120(%rsp), %rsi
addq $0xc, %rsi
callq 0x34020
movq %rax, %rcx
movq 0x68(%rsp), %rax
movq %rcx, 0xf8(%rsp)
movb %dl, 0x100(%rsp)
movq 0x120(%rsp), %rcx
movw 0x8(%rcx), %cx
movw %cx, 0x48(%rax)
movq 0x40(%rax), %rdi
movq 0x118(%rsp), %rax
movzwl 0x22(%rax), %eax
movl %eax, %esi
callq 0xcdd0
movq (%rax), %rdi
movq 0x118(%rsp), %rsi
movq (%rdi), %rax
callq *0x30(%rax)
movq 0x68(%rsp), %rdi
callq 0x40560
movq 0x68(%rsp), %rdi
addq $0xf8, %rdi
callq 0x34370
cmpq $0x0, %rax
jbe 0x401f2
movq 0x68(%rsp), %rcx
movzwl 0x4a(%rcx), %eax
movzwl 0x4c(%rcx), %ecx
subl $0x1, %ecx
cmpl %ecx, %eax
jge 0x3ff7f
movq 0x68(%rsp), %rcx
movzwl 0x4a(%rcx), %eax
addl $0x1, %eax
movzwl 0x48(%rcx), %ecx
cmpl %ecx, %eax
je 0x401eb
jmp 0x3ff91
movq 0x68(%rsp), %rax
movzwl 0x48(%rax), %eax
cmpl $0x0, %eax
je 0x401eb
movq 0x68(%rsp), %rdi
addq $0xb0, %rdi
callq 0x343a0
cmpq $0x0, %rax
jbe 0x401eb
movq 0x68(%rsp), %rdi
addq $0xf8, %rdi
callq 0x343b0
movq 0x68(%rsp), %rdi
movq (%rax), %rax
movq %rax, 0xf0(%rsp)
addq $0xf8, %rdi
callq 0x343e0
movq 0x68(%rsp), %rdi
movq %rdi, %rax
addq $0x48, %rax
addq $0x30, %rax
movq %rax, 0x60(%rsp)
addq $0xb0, %rdi
callq 0x34410
movq %rax, 0xe0(%rsp)
leaq 0xe0(%rsp), %rdi
callq 0x34440
movq 0x60(%rsp), %rdi
movzwl (%rax), %eax
movq %rax, 0xe8(%rsp)
leaq 0xe8(%rsp), %rsi
callq 0x34310
cmpq $0x0, (%rax)
je 0x4007d
movq 0x99fb7(%rip), %rdi     # 0xd9ff0
leaq 0x6a8a8(%rip), %rsi     # 0xaa8e8
callq 0x8440
movq 0x99fa4(%rip), %rdi     # 0xd9ff0
leaq 0x6c06f(%rip), %rsi     # 0xac0c2
callq 0x8440
movq %rax, %rdi
movq 0x99ef6(%rip), %rsi     # 0xd9f58
callq 0x8480
movq 0x99f62(%rip), %rdi     # 0xd9fd0
callq 0x84f0
movl $0x1, %edi
callq 0x8500
movq 0x68(%rsp), %rdi
addq $0xb0, %rdi
callq 0x34410
movq %rax, 0xd8(%rsp)
leaq 0xd8(%rsp), %rdi
callq 0x34440
movq 0x68(%rsp), %rdi
movw (%rax), %cx
movq 0xf0(%rsp), %rax
movw %cx, 0x20(%rax)
movq 0xf0(%rsp), %rax
movq %rax, 0x48(%rsp)
movq %rdi, %rax
addq $0x48, %rax
addq $0x30, %rax
movq %rax, 0x40(%rsp)
addq $0xb0, %rdi
callq 0x34410
movq %rax, 0xc8(%rsp)
leaq 0xc8(%rsp), %rdi
callq 0x34440
movq 0x40(%rsp), %rdi
movzwl (%rax), %eax
movq %rax, 0xd0(%rsp)
leaq 0xd0(%rsp), %rsi
callq 0x34310
movq 0x48(%rsp), %rcx
movq 0x68(%rsp), %rdi
movq %rcx, (%rax)
movq %rdi, %rax
addq $0xb0, %rax
movq %rax, 0x50(%rsp)
addq $0xb0, %rdi
callq 0x34410
movq 0x50(%rsp), %rdi
movq %rax, 0xc0(%rsp)
movq 0xc0(%rsp), %rsi
callq 0x34460
movq %rax, %rcx
movq 0x68(%rsp), %rax
movq %rcx, 0xb8(%rsp)
movq 0xf0(%rsp), %rcx
movq %rcx, 0x58(%rsp)
movq %rax, %rdi
addq $0xe0, %rdi
movzwl 0x4a(%rax), %eax
movl %eax, %esi
callq 0x344b0
movq 0x58(%rsp), %rdx
movq 0x68(%rsp), %rcx
movq %rdx, (%rax)
movw 0x4a(%rcx), %ax
addw $0x1, %ax
movw %ax, 0x4a(%rcx)
movzwl 0x4a(%rcx), %eax
movzwl 0x4c(%rcx), %ecx
cmpl %ecx, %eax
jne 0x401b5
movq 0x68(%rsp), %rax
movw $0x0, 0x4a(%rax)
jmp 0x401b7
callq 0x46500
movq %rax, %rdi
callq 0x46c50
movq %rax, %rdx
movq 0x68(%rsp), %rax
movq 0xf0(%rsp), %rcx
movq %rdx, 0x8(%rcx)
movq 0x38(%rax), %rdi
movq 0x50(%rax), %rsi
movzwl 0x4a(%rax), %edx
callq 0x3f620
jmp 0x401ed
jmp 0x401f2
jmp 0x3ff36
movq 0x120(%rsp), %rax
movq %rax, 0x38(%rsp)
cmpq $0x0, %rax
je 0x4020f
movq 0x38(%rsp), %rdi
callq 0x8410
movq 0x68(%rsp), %rdi
addq $0x110, %rdi            # imm = 0x110
callq 0x409c0
cmpq $0x0, %rax
jbe 0x4025d
callq 0x46500
movq %rax, 0x30(%rsp)
callq 0x46500
movq %rax, %rdi
callq 0x46c50
movq 0x30(%rsp), %rdi
movq 0x68(%rsp), %rdx
movq %rax, %rsi
addq 0x30(%rdx), %rsi
xorl %eax, %eax
movl %eax, %ecx
movl $0x1, %r8d
callq 0x46c60
jmp 0x40554
movq 0x68(%rsp), %rdi
addq $0x160, %rdi            # imm = 0x160
callq 0x409d0
movq 0x68(%rsp), %rdi
movq (%rax), %rax
movq %rax, 0xb0(%rsp)
addq $0x160, %rdi            # imm = 0x160
callq 0x409e0
movq 0x68(%rsp), %rcx
movzwl 0x4a(%rcx), %eax
movzwl 0x4c(%rcx), %ecx
subl $0x1, %ecx
cmpl %ecx, %eax
jge 0x402b9
movq 0x68(%rsp), %rcx
movzwl 0x4a(%rcx), %eax
addl $0x1, %eax
movzwl 0x48(%rcx), %ecx
cmpl %ecx, %eax
je 0x402de
jmp 0x402c7
movq 0x68(%rsp), %rax
movzwl 0x48(%rax), %eax
cmpl $0x0, %eax
je 0x402de
movq 0x68(%rsp), %rdi
addq $0xb0, %rdi
callq 0x343a0
cmpq $0x0, %rax
jne 0x402fc
movq 0x68(%rsp), %rdi
addq $0xf8, %rdi
leaq 0xb0(%rsp), %rsi
callq 0x344d0
jmp 0x40509
movq 0x68(%rsp), %rdi
movq %rdi, %rax
addq $0x48, %rax
addq $0x30, %rax
movq %rax, 0x28(%rsp)
addq $0xb0, %rdi
callq 0x34410
movq %rax, 0xa0(%rsp)
leaq 0xa0(%rsp), %rdi
callq 0x34440
movq 0x28(%rsp), %rdi
movzwl (%rax), %eax
movq %rax, 0xa8(%rsp)
leaq 0xa8(%rsp), %rsi
callq 0x34310
cmpq $0x0, (%rax)
je 0x403a0
movq 0x99c94(%rip), %rdi     # 0xd9ff0
leaq 0x6a585(%rip), %rsi     # 0xaa8e8
callq 0x8440
movq 0x99c81(%rip), %rdi     # 0xd9ff0
leaq 0x6b7c8(%rip), %rsi     # 0xabb3e
callq 0x8440
movq %rax, %rdi
movq 0x99bd3(%rip), %rsi     # 0xd9f58
callq 0x8480
movq 0x99c3f(%rip), %rdi     # 0xd9fd0
callq 0x84f0
movl $0x1, %edi
callq 0x8500
movq 0x68(%rsp), %rdi
addq $0xb0, %rdi
callq 0x34410
movq %rax, 0x98(%rsp)
leaq 0x98(%rsp), %rdi
callq 0x34440
movq 0x68(%rsp), %rdi
movw (%rax), %cx
movq 0xb0(%rsp), %rax
movw %cx, 0x20(%rax)
movq 0xb0(%rsp), %rax
movq %rax, 0x10(%rsp)
movq %rdi, %rax
addq $0x48, %rax
addq $0x30, %rax
movq %rax, 0x8(%rsp)
addq $0xb0, %rdi
callq 0x34410
movq %rax, 0x88(%rsp)
leaq 0x88(%rsp), %rdi
callq 0x34440
movq 0x8(%rsp), %rdi
movzwl (%rax), %eax
movq %rax, 0x90(%rsp)
leaq 0x90(%rsp), %rsi
callq 0x34310
movq 0x10(%rsp), %rcx
movq 0x68(%rsp), %rdi
movq %rcx, (%rax)
movq %rdi, %rax
addq $0xb0, %rax
movq %rax, 0x18(%rsp)
addq $0xb0, %rdi
callq 0x34410
movq 0x18(%rsp), %rdi
movq %rax, 0x80(%rsp)
movq 0x80(%rsp), %rsi
callq 0x34460
movq %rax, %rcx
movq 0x68(%rsp), %rax
movq %rcx, 0x78(%rsp)
movq 0xb0(%rsp), %rcx
movq %rcx, 0x20(%rsp)
movq %rax, %rdi
addq $0xe0, %rdi
movzwl 0x4a(%rax), %eax
movl %eax, %esi
callq 0x344b0
movq 0x20(%rsp), %rdx
movq 0x68(%rsp), %rcx
movq %rdx, (%rax)
movw 0x4a(%rcx), %ax
addw $0x1, %ax
movw %ax, 0x4a(%rcx)
movzwl 0x4a(%rcx), %eax
movzwl 0x4c(%rcx), %ecx
cmpl %ecx, %eax
jne 0x404d5
movq 0x68(%rsp), %rax
movw $0x0, 0x4a(%rax)
jmp 0x404d7
callq 0x46500
movq %rax, %rdi
callq 0x46c50
movq %rax, %rdx
movq 0x68(%rsp), %rax
movq 0xb0(%rsp), %rcx
movq %rdx, 0x8(%rcx)
movq 0x38(%rax), %rdi
movq 0x50(%rax), %rsi
movzwl 0x4a(%rax), %edx
callq 0x3f620
movq 0x68(%rsp), %rdi
addq $0x160, %rdi            # imm = 0x160
callq 0x409f0
cmpq $0x0, %rax
jbe 0x40552
callq 0x46500
movq %rax, (%rsp)
callq 0x46500
movq %rax, %rdi
callq 0x46c50
movq (%rsp), %rdi
movq 0x68(%rsp), %rdx
movq %rax, %rsi
addq 0x30(%rdx), %rsi
xorl %eax, %eax
movl %eax, %ecx
xorl %r8d, %r8d
callq 0x46c60
jmp 0x40554
addq $0x138, %rsp            # imm = 0x138
retq
nopl (%rax)