// File: CMU-SAFARI[P]MQSim/src/host/IO_Flow_Synthetic.cpp
// Function: Host_Components::IO_Flow_Synthetic::Generate_next_request()
Host_IO_Request* IO_Flow_Synthetic::Generate_next_request()
	{
		if (stop_time > 0) {
			if (Simulator->Time() > stop_time) {
				return NULL;
			}
		} else if (STAT_generated_request_count >= total_requests_to_be_generated) {
			return NULL;
		}
		
		Host_IO_Request* request = new Host_IO_Request;
		if (random_request_type_generator->Uniform(0, 1) <= read_ratio) {
			request->Type = Host_IO_Request_Type::READ;
			STAT_generated_read_request_count++;
		} else {
			request->Type = Host_IO_Request_Type::WRITE;
			STAT_generated_write_request_count++;
		}

		switch (request_size_distribution) {
			case Utils::Request_Size_Distribution_Type::FIXED:
				request->LBA_count = average_request_size;
				break;
			case Utils::Request_Size_Distribution_Type::NORMAL:
			{
				double temp_request_size = random_request_size_generator->Normal(average_request_size, variance_request_size);
				request->LBA_count = (unsigned int)(ceil(temp_request_size));
				if (request->LBA_count <= 0) {
					request->LBA_count = 1;
				}
				break;
			}
			default:
				throw std::invalid_argument("Uknown distribution type for requset size.");
		}

		switch (address_distribution) {
			case Utils::Address_Distribution_Type::STREAMING:
				request->Start_LBA = streaming_next_address;
				if (request->Start_LBA + request->LBA_count > end_lsa_on_device) {
					request->Start_LBA = start_lsa_on_device;
				}
				streaming_next_address += request->LBA_count;
				if (streaming_next_address > end_lsa_on_device) {
					streaming_next_address = start_lsa_on_device;
				}
				if (generate_aligned_addresses) {
					if(streaming_next_address % alignment_value != 0) {
						streaming_next_address += alignment_value - (streaming_next_address % alignment_value);
					}
				}
				if(streaming_next_address == request->Start_LBA) {
					PRINT_MESSAGE("Synthetic Message Generator: The same address is always repeated due to configuration parameters!")
				}
				break;
			case Utils::Address_Distribution_Type::RANDOM_HOTCOLD:
				// (100-hot)% of requests going to hot% of the address space
				if (random_hot_cold_generator->Uniform(0, 1) < hot_region_ratio) {
					request->Start_LBA = random_hot_address_generator->Uniform_ulong(hot_region_end_lsa + 1, end_lsa_on_device);
					if (request->Start_LBA < hot_region_end_lsa + 1 || request->Start_LBA > end_lsa_on_device) {
						PRINT_ERROR("Out of range address is generated in IO_Flow_Synthetic!\n")
						if (request->Start_LBA + request->LBA_count > end_lsa_on_device) {
							request->Start_LBA = hot_region_end_lsa + 1;
						}
					}
				} else {
					request->Start_LBA = random_hot_address_generator->Uniform_ulong(start_lsa_on_device, hot_region_end_lsa);
					if (request->Start_LBA < start_lsa_on_device || request->Start_LBA > hot_region_end_lsa) {
						PRINT_ERROR("Out of range address is generated in IO_Flow_Synthetic!\n")
					}
				}
				break;
			case Utils::Address_Distribution_Type::RANDOM_UNIFORM:
				request->Start_LBA = random_address_generator->Uniform_ulong(start_lsa_on_device, end_lsa_on_device);
				if (request->Start_LBA < start_lsa_on_device || request->Start_LBA > end_lsa_on_device) {
					PRINT_ERROR("Out of range address is generated in IO_Flow_Synthetic!\n")
				}
				if (request->Start_LBA + request->LBA_count > end_lsa_on_device) {
					request->Start_LBA = start_lsa_on_device;
				}
				break;
			default:
				PRINT_ERROR("Unknown address distribution type!\n")
		}

		if (generate_aligned_addresses) {
			request->Start_LBA -= request->Start_LBA % alignment_value;
		}
		STAT_generated_request_count++;
		request->Arrival_time = Simulator->Time();
		DEBUG("* Host: Request generated - " << (request->Type == Host_IO_Request_Type::READ ? "Read, " : "Write, ") << "LBA:" << request->Start_LBA << ", Size_in_bytes:" << request->LBA_count << "")

		return request;
	}

// Assembly:
subq $0x58, %rsp
movq %rdi, 0x48(%rsp)
movq 0x48(%rsp), %rax
movq %rax, 0x20(%rsp)
cmpq $0x0, 0x48(%rax)
jbe 0x38602
callq 0x46500
movq %rax, %rdi
callq 0x46c50
movq 0x20(%rsp), %rcx
cmpq 0x48(%rcx), %rax
jbe 0x38600
movq $0x0, 0x50(%rsp)
jmp 0x38bf6
jmp 0x38622
movq 0x20(%rsp), %rcx
movl 0x150(%rcx), %eax
cmpl 0x50(%rcx), %eax
jb 0x38620
movq $0x0, 0x50(%rsp)
jmp 0x38bf6
jmp 0x38622
movl $0x28, %edi
callq 0x8450
movq %rax, %rcx
movq 0x20(%rsp), %rax
movq %rcx, 0x40(%rsp)
movq 0x480(%rax), %rdi
xorps %xmm0, %xmm0
movsd 0x73675(%rip), %xmm1    # 0xabcc0
callq 0xa6f80
movq 0x20(%rsp), %rax
movaps %xmm0, %xmm1
movsd 0x470(%rax), %xmm0
ucomisd %xmm1, %xmm0
jb 0x38688
movq 0x20(%rsp), %rax
movq 0x40(%rsp), %rcx
movl $0x0, 0x1c(%rcx)
movl 0x154(%rax), %ecx
addl $0x1, %ecx
movl %ecx, 0x154(%rax)
jmp 0x386a8
movq 0x20(%rsp), %rax
movq 0x40(%rsp), %rcx
movl $0x1, 0x1c(%rcx)
movl 0x158(%rax), %ecx
addl $0x1, %ecx
movl %ecx, 0x158(%rax)
movq 0x20(%rsp), %rax
movl 0x4d8(%rax), %eax
movl %eax, 0x1c(%rsp)
testl %eax, %eax
je 0x386c8
jmp 0x386bd
movl 0x1c(%rsp), %eax
subl $0x1, %eax
je 0x386e0
jmp 0x38740
movq 0x20(%rsp), %rax
movl 0x4dc(%rax), %ecx
movq 0x40(%rsp), %rax
movl %ecx, 0x18(%rax)
jmp 0x38798
movq 0x20(%rsp), %rax
movq 0x4e8(%rax), %rdi
movl 0x4dc(%rax), %ecx
movl 0x4e0(%rax), %eax
cvtsi2sd %rcx, %xmm0
cvtsi2sd %rax, %xmm1
callq 0xa7430
movsd %xmm0, 0x38(%rsp)
movsd 0x38(%rsp), %xmm0
callq 0x8090
cvttsd2si %xmm0, %rax
movl %eax, %ecx
movq 0x40(%rsp), %rax
movl %ecx, 0x18(%rax)
movq 0x40(%rsp), %rax
cmpl $0x0, 0x18(%rax)
ja 0x3873e
movq 0x40(%rsp), %rax
movl $0x1, 0x18(%rax)
jmp 0x38798
movl $0x10, %edi
callq 0x8200
movq %rax, %rdi
movq %rdi, %rax
movq %rax, 0x10(%rsp)
leaq 0x735f7(%rip), %rsi     # 0xabd53
callq 0x87d0
jmp 0x38763
movq 0x10(%rsp), %rdi
movq 0xa1859(%rip), %rsi     # 0xd9fc8
movq 0xa183a(%rip), %rdx     # 0xd9fb0
callq 0x8710
movq 0x10(%rsp), %rdi
movq %rax, %rcx
movl %edx, %eax
movq %rcx, 0x30(%rsp)
movl %eax, 0x2c(%rsp)
callq 0x8330
jmp 0x38c00
movq 0x20(%rsp), %rax
movl 0x48c(%rax), %eax
movl %eax, 0xc(%rsp)
subl $0x1, %eax
je 0x387cf
jmp 0x387ae
movl 0xc(%rsp), %eax
subl $0x2, %eax
je 0x38a73
jmp 0x387bd
movl 0xc(%rsp), %eax
subl $0x3, %eax
je 0x388ea
jmp 0x38b3e
movq 0x20(%rsp), %rcx
movq 0x4d0(%rcx), %rdx
movq 0x40(%rsp), %rax
movq %rdx, 0x10(%rax)
movq 0x40(%rsp), %rax
movq 0x10(%rax), %rax
movq 0x40(%rsp), %rdx
movl 0x18(%rdx), %edx
addq %rdx, %rax
cmpq 0x70(%rcx), %rax
jbe 0x38810
movq 0x20(%rsp), %rax
movq 0x68(%rax), %rcx
movq 0x40(%rsp), %rax
movq %rcx, 0x10(%rax)
movq 0x20(%rsp), %rcx
movq 0x40(%rsp), %rax
movl 0x18(%rax), %eax
addq 0x4d0(%rcx), %rax
movq %rax, 0x4d0(%rcx)
movq 0x4d0(%rcx), %rax
cmpq 0x70(%rcx), %rax
jbe 0x38848
movq 0x20(%rsp), %rax
movq 0x68(%rax), %rcx
movq %rcx, 0x4d0(%rax)
movq 0x20(%rsp), %rax
testb $0x1, 0x514(%rax)
je 0x388ac
movq 0x20(%rsp), %rcx
movq 0x4d0(%rcx), %rax
movl 0x518(%rcx), %ecx
xorl %edx, %edx
divq %rcx
cmpq $0x0, %rdx
je 0x388aa
movq 0x20(%rsp), %rdx
movl 0x518(%rdx), %eax
movl %eax, %ecx
movq 0x4d0(%rdx), %rax
movl 0x518(%rdx), %edx
movl %edx, %esi
xorl %edx, %edx
divq %rsi
movq 0x20(%rsp), %rax
subq %rdx, %rcx
addq 0x4d0(%rax), %rcx
movq %rcx, 0x4d0(%rax)
jmp 0x388ac
movq 0x20(%rsp), %rax
movq 0x4d0(%rax), %rax
movq 0x40(%rsp), %rcx
cmpq 0x10(%rcx), %rax
jne 0x388e5
movq 0xa16ce(%rip), %rdi     # 0xd9f98
leaq 0x734ad(%rip), %rsi     # 0xabd7e
callq 0x8440
movq %rax, %rdi
movq 0xa1678(%rip), %rsi     # 0xd9f58
callq 0x8480
jmp 0x38b89
movq 0x20(%rsp), %rax
movq 0x4a8(%rax), %rdi
xorps %xmm0, %xmm0
movsd 0x733bf(%rip), %xmm1    # 0xabcc0
callq 0xa6f80
movq 0x20(%rsp), %rax
movaps %xmm0, %xmm1
movsd 0x490(%rax), %xmm0
ucomisd %xmm1, %xmm0
jbe 0x389ce
movq 0x20(%rsp), %rax
movq 0x4b8(%rax), %rdi
movq 0x4c8(%rax), %rsi
addq $0x1, %rsi
movq 0x70(%rax), %rdx
callq 0xa70a0
movq 0x20(%rsp), %rcx
movq %rax, %rdx
movq 0x40(%rsp), %rax
movq %rdx, 0x10(%rax)
movq 0x40(%rsp), %rax
movq 0x10(%rax), %rax
movq 0x4c8(%rcx), %rcx
addq $0x1, %rcx
cmpq %rcx, %rax
jb 0x3897e
movq 0x20(%rsp), %rcx
movq 0x40(%rsp), %rax
movq 0x10(%rax), %rax
cmpq 0x70(%rcx), %rax
jbe 0x389c9
movq 0xa166b(%rip), %rdi     # 0xd9ff0
leaq 0x71f5c(%rip), %rsi     # 0xaa8e8
callq 0x8440
movq 0xa1658(%rip), %rdi     # 0xd9ff0
leaq 0x73441(%rip), %rsi     # 0xabde0
callq 0x8440
movq %rax, %rdi
movq 0xa15aa(%rip), %rsi     # 0xd9f58
callq 0x8480
movq 0xa1616(%rip), %rdi     # 0xd9fd0
callq 0x84f0
movl $0x1, %edi
callq 0x8500
jmp 0x38a6e
movq 0x20(%rsp), %rax
movq 0x4b8(%rax), %rdi
movq 0x68(%rax), %rsi
movq 0x4c8(%rax), %rdx
callq 0xa70a0
movq 0x20(%rsp), %rcx
movq %rax, %rdx
movq 0x40(%rsp), %rax
movq %rdx, 0x10(%rax)
movq 0x40(%rsp), %rax
movq 0x10(%rax), %rax
cmpq 0x68(%rcx), %rax
jb 0x38a21
movq 0x20(%rsp), %rcx
movq 0x40(%rsp), %rax
movq 0x10(%rax), %rax
cmpq 0x4c8(%rcx), %rax
jbe 0x38a6c
movq 0xa15c8(%rip), %rdi     # 0xd9ff0
leaq 0x71eb9(%rip), %rsi     # 0xaa8e8
callq 0x8440
movq 0xa15b5(%rip), %rdi     # 0xd9ff0
leaq 0x7339e(%rip), %rsi     # 0xabde0
callq 0x8440
movq %rax, %rdi
movq 0xa1507(%rip), %rsi     # 0xd9f58
callq 0x8480
movq 0xa1573(%rip), %rdi     # 0xd9fd0
callq 0x84f0
movl $0x1, %edi
callq 0x8500
jmp 0x38a6e
jmp 0x38b89
movq 0x20(%rsp), %rax
movq 0x498(%rax), %rdi
movq 0x68(%rax), %rsi
movq 0x70(%rax), %rdx
callq 0xa70a0
movq 0x20(%rsp), %rcx
movq %rax, %rdx
movq 0x40(%rsp), %rax
movq %rdx, 0x10(%rax)
movq 0x40(%rsp), %rax
movq 0x10(%rax), %rax
cmpq 0x68(%rcx), %rax
jb 0x38ac0
movq 0x20(%rsp), %rcx
movq 0x40(%rsp), %rax
movq 0x10(%rax), %rax
cmpq 0x70(%rcx), %rax
jbe 0x38b0b
movq 0xa1529(%rip), %rdi     # 0xd9ff0
leaq 0x71e1a(%rip), %rsi     # 0xaa8e8
callq 0x8440
movq 0xa1516(%rip), %rdi     # 0xd9ff0
leaq 0x732ff(%rip), %rsi     # 0xabde0
callq 0x8440
movq %rax, %rdi
movq 0xa1468(%rip), %rsi     # 0xd9f58
callq 0x8480
movq 0xa14d4(%rip), %rdi     # 0xd9fd0
callq 0x84f0
movl $0x1, %edi
callq 0x8500
movq 0x20(%rsp), %rcx
movq 0x40(%rsp), %rax
movq 0x10(%rax), %rax
movq 0x40(%rsp), %rdx
movl 0x18(%rdx), %edx
addq %rdx, %rax
cmpq 0x70(%rcx), %rax
jbe 0x38b3c
movq 0x20(%rsp), %rax
movq 0x68(%rax), %rcx
movq 0x40(%rsp), %rax
movq %rcx, 0x10(%rax)
jmp 0x38b89
movq 0xa14ab(%rip), %rdi     # 0xd9ff0
leaq 0x71d9c(%rip), %rsi     # 0xaa8e8
callq 0x8440
movq 0xa1498(%rip), %rdi     # 0xd9ff0
leaq 0x732ba(%rip), %rsi     # 0xabe19
callq 0x8440
movq %rax, %rdi
movq 0xa13ea(%rip), %rsi     # 0xd9f58
callq 0x8480
movq 0xa1456(%rip), %rdi     # 0xd9fd0
callq 0x84f0
movl $0x1, %edi
callq 0x8500
movq 0x20(%rsp), %rax
testb $0x1, 0x514(%rax)
je 0x38bc0
movq 0x20(%rsp), %rcx
movq 0x40(%rsp), %rax
movq 0x10(%rax), %rax
movl 0x518(%rcx), %ecx
xorl %edx, %edx
divq %rcx
movq 0x40(%rsp), %rax
movq 0x10(%rax), %rcx
subq %rdx, %rcx
movq %rcx, 0x10(%rax)
movq 0x20(%rsp), %rax
movl 0x150(%rax), %ecx
addl $0x1, %ecx
movl %ecx, 0x150(%rax)
callq 0x46500
movq %rax, %rdi
callq 0x46c50
movq %rax, %rcx
movq 0x40(%rsp), %rax
movq %rcx, (%rax)
movq 0x40(%rsp), %rax
movq %rax, 0x50(%rsp)
movq 0x50(%rsp), %rax
addq $0x58, %rsp
retq
movq 0x30(%rsp), %rdi
callq 0x8770
nopw (%rax,%rax)