// File: CMU-SAFARI[P]MQSim/src/main.cpp
// Function: main
int main(int argc, char* argv[])
{
	string ssd_config_file_path, workload_defs_file_path;
	if (argc != 5) {
		// MQSim expects 2 arguments: 1) the path to the SSD configuration definition file, and 2) the path to the workload definition file
		print_help();
		return 1;
	}

	command_line_args(argv, ssd_config_file_path, workload_defs_file_path);

	Execution_Parameter_Set* exec_params = new Execution_Parameter_Set;
	read_configuration_parameters(ssd_config_file_path, exec_params);
	std::vector<std::vector<IO_Flow_Parameter_Set*>*>* io_scenarios = read_workload_definitions(workload_defs_file_path);

	int cntr = 1;
	for (auto io_scen = io_scenarios->begin(); io_scen != io_scenarios->end(); io_scen++, cntr++) {
		time_t start_time = time(0);
		char* dt = ctime(&start_time);
		PRINT_MESSAGE("MQSim started at " << dt)
		PRINT_MESSAGE("******************************")
		PRINT_MESSAGE("Executing scenario " << cntr << " out of " << io_scenarios->size() << " .......")

		//The simulator should always be reset, before starting the actual simulation
		Simulator->Reset();

		exec_params->Host_Configuration.IO_Flow_Definitions.clear();
		for (auto io_flow_def = (*io_scen)->begin(); io_flow_def != (*io_scen)->end(); io_flow_def++) {
			exec_params->Host_Configuration.IO_Flow_Definitions.push_back(*io_flow_def);
		}

		SSD_Device ssd(&exec_params->SSD_Device_Configuration, &exec_params->Host_Configuration.IO_Flow_Definitions);//Create SSD_Device based on the specified parameters
		exec_params->Host_Configuration.Input_file_path = workload_defs_file_path.substr(0, workload_defs_file_path.find_last_of("."));//Create Host_System based on the specified parameters
		Host_System host(&exec_params->Host_Configuration, exec_params->SSD_Device_Configuration.Enabled_Preconditioning, ssd.Host_interface);
		host.Attach_ssd_device(&ssd);

		Simulator->Start_simulation();

		time_t end_time = time(0);
		dt = ctime(&end_time);
		PRINT_MESSAGE("MQSim finished at " << dt)
		uint64_t duration = (uint64_t)difftime(end_time, start_time);
		PRINT_MESSAGE("Total simulation time: " << duration / 3600 << ":" << (duration % 3600) / 60 << ":" << ((duration % 3600) % 60))
		PRINT_MESSAGE("");

		PRINT_MESSAGE("Writing results to output file .......");
		collect_results(ssd, host, (workload_defs_file_path.substr(0, workload_defs_file_path.find_last_of(".")) + "_scenario_" + std::to_string(cntr) + ".xml").c_str());
	}
    cout << "Simulation complete; Press any key to exit." << endl;

	cin.get(); // Disable if you prefer batch runs

	return 0;
}

// Assembly:
subq $0x3a8, %rsp            # imm = 0x3A8
movl $0x0, 0x3a4(%rsp)
movl %edi, 0x3a0(%rsp)
movq %rsi, 0x398(%rsp)
leaq 0x378(%rsp), %rdi
callq 0x85e0
leaq 0x358(%rsp), %rdi
callq 0x85e0
cmpl $0x5, 0x3a0(%rsp)
je 0xbca0
callq 0xbbb0
jmp 0xbc6c
movl $0x1, 0x3a4(%rsp)
movl $0x1, 0x348(%rsp)
jmp 0xc5ef
movq %rax, %rcx
movl %edx, %eax
movq %rcx, 0x350(%rsp)
movl %eax, 0x34c(%rsp)
jmp 0xc618
movq 0x398(%rsp), %rdi
leaq 0x378(%rsp), %rsi
leaq 0x358(%rsp), %rdx
callq 0x9ab0
jmp 0xbcbf
movl $0x8, %edi
callq 0x8450
movq %rax, 0xd8(%rsp)
jmp 0xbcd3
movq 0xd8(%rsp), %rdi
callq 0xca50
movq 0xd8(%rsp), %rax
movq %rax, 0x340(%rsp)
leaq 0x320(%rsp), %rdi
leaq 0x378(%rsp), %rsi
callq 0x81a0
jmp 0xbd07
movq 0x340(%rsp), %rsi
leaq 0x320(%rsp), %rdi
callq 0x9c90
jmp 0xbd1e
leaq 0x320(%rsp), %rdi
callq 0x8848
leaq 0x2f8(%rsp), %rdi
leaq 0x358(%rsp), %rsi
callq 0x81a0
jmp 0xbd42
leaq 0x2f8(%rsp), %rdi
callq 0xa3f0
movq %rax, 0xd0(%rsp)
jmp 0xbd59
leaq 0x2f8(%rsp), %rdi
callq 0x8848
movq 0xd0(%rsp), %rax
movq %rax, 0x318(%rsp)
movl $0x1, 0x2f4(%rsp)
movq 0x318(%rsp), %rdi
callq 0xce80
movq %rax, 0x2e8(%rsp)
movq 0x318(%rsp), %rdi
callq 0xcef0
movq %rax, 0x2e0(%rsp)
leaq 0x2e8(%rsp), %rdi
leaq 0x2e0(%rsp), %rsi
callq 0xceb0
testb $0x1, %al
jne 0xbdc9
jmp 0xc59e
xorl %eax, %eax
movl %eax, %edi
callq 0x83f0
movq %rax, 0x2d8(%rsp)
leaq 0x2d8(%rsp), %rdi
callq 0x8170
movq %rax, 0x2d0(%rsp)
movq 0xce1a2(%rip), %rdi     # 0xd9f98
leaq 0x9d5f9(%rip), %rsi     # 0xa93f6
callq 0x8440
movq %rax, 0xc8(%rsp)
jmp 0xbe0c
movq 0xc8(%rsp), %rdi
movq 0x2d0(%rsp), %rsi
callq 0x8440
movq %rax, 0xc0(%rsp)
jmp 0xbe2b
movq 0xc0(%rsp), %rdi
movq 0xce11e(%rip), %rsi     # 0xd9f58
callq 0x8480
jmp 0xbe41
movq 0xce150(%rip), %rdi     # 0xd9f98
leaq 0x9d5b9(%rip), %rsi     # 0xa9408
callq 0x8440
movq %rax, 0xb8(%rsp)
jmp 0xbe5e
movq 0xb8(%rsp), %rdi
movq 0xce0eb(%rip), %rsi     # 0xd9f58
callq 0x8480
jmp 0xbe74
movq 0xce11d(%rip), %rdi     # 0xd9f98
leaq 0x9d5a5(%rip), %rsi     # 0xa9427
callq 0x8440
movq %rax, 0xb0(%rsp)
jmp 0xbe91
movq 0xb0(%rsp), %rdi
movl 0x2f4(%rsp), %esi
callq 0x8730
movq %rax, 0xa8(%rsp)
jmp 0xbeaf
movq 0xa8(%rsp), %rdi
leaq 0x9d57d(%rip), %rsi     # 0xa943b
callq 0x8440
movq %rax, 0xa0(%rsp)
jmp 0xbecd
movq 0x318(%rsp), %rdi
callq 0xcf20
movq 0xa0(%rsp), %rdi
movq %rax, %rsi
callq 0x8100
movq %rax, 0x98(%rsp)
jmp 0xbef4
movq 0x98(%rsp), %rdi
leaq 0x9d58a(%rip), %rsi     # 0xa948d
callq 0x8440
movq %rax, 0x90(%rsp)
jmp 0xbf12
movq 0x90(%rsp), %rdi
movq 0xce037(%rip), %rsi     # 0xd9f58
callq 0x8480
jmp 0xbf28
callq 0x46500
movq %rax, 0x88(%rsp)
jmp 0xbf37
movq 0x88(%rsp), %rdi
callq 0x46570
jmp 0xbf46
leaq 0xce70b(%rip), %rdi     # 0xda658
callq 0xcf40
leaq 0x2e8(%rsp), %rdi
callq 0xcf60
movq (%rax), %rdi
callq 0xcf70
movq %rax, 0x2c8(%rsp)
leaq 0x2e8(%rsp), %rdi
callq 0xcf60
movq (%rax), %rdi
callq 0xcfe0
movq %rax, 0x2c0(%rsp)
leaq 0x2c8(%rsp), %rdi
leaq 0x2c0(%rsp), %rsi
callq 0xcfa0
testb $0x1, %al
jne 0xbfaa
jmp 0xc02f
leaq 0x2c8(%rsp), %rdi
callq 0xd010
movq %rax, %rsi
leaq 0xce697(%rip), %rdi     # 0xda658
callq 0xcb90
jmp 0xbfc8
jmp 0xbfca
leaq 0x2c8(%rsp), %rdi
xorl %esi, %esi
callq 0xd020
movq %rax, 0x2b8(%rsp)
jmp 0xbf6f
movq %rax, %rcx
movl %edx, %eax
movq %rcx, 0x350(%rsp)
movl %eax, 0x34c(%rsp)
leaq 0x320(%rsp), %rdi
callq 0x8848
jmp 0xc618
movq %rax, %rcx
movl %edx, %eax
movq %rcx, 0x350(%rsp)
movl %eax, 0x34c(%rsp)
leaq 0x2f8(%rsp), %rdi
callq 0x8848
jmp 0xc618
leaq 0xce4aa(%rip), %rsi     # 0xda4e0
leaq 0xce61b(%rip), %rdx     # 0xda658
leaq 0x238(%rsp), %rdi
callq 0x29300
jmp 0xc04c
leaq 0x9d441(%rip), %rsi     # 0xa9494
leaq 0x358(%rsp), %rdi
movq %rdi, 0x80(%rsp)
movq $-0x1, %rdx
callq 0x8420
movq 0x80(%rsp), %rsi
movq %rax, %rcx
xorl %eax, %eax
movl %eax, %edx
leaq 0x218(%rsp), %rdi
callq 0x8460
jmp 0xc08d
leaq 0xce5a4(%rip), %rdi     # 0xda638
leaq 0x218(%rsp), %rsi
movq %rsi, 0x78(%rsp)
callq 0x8510
movq 0x78(%rsp), %rdi
callq 0x8848
leaq 0xce385(%rip), %rax     # 0xda43c
movq 0x278(%rsp), %rcx
movzbl (%rax), %edx
andl $0x1, %edx
leaq 0xce40c(%rip), %rsi     # 0xda4d8
leaq 0x198(%rsp), %rdi
callq 0x1de40
jmp 0xc0db
leaq 0x198(%rsp), %rdi
leaq 0x238(%rsp), %rsi
callq 0x1f410
jmp 0xc0f2
callq 0x46500
movq %rax, 0x70(%rsp)
jmp 0xc0fe
movq 0x70(%rsp), %rdi
callq 0x46a20
jmp 0xc10a
xorl %eax, %eax
movl %eax, %edi
callq 0x83f0
movq %rax, 0x190(%rsp)
leaq 0x190(%rsp), %rdi
callq 0x8170
movq %rax, 0x2d0(%rsp)
movq 0xcde61(%rip), %rdi     # 0xd9f98
leaq 0x9d306(%rip), %rsi     # 0xa9444
callq 0x8440
movq %rax, 0x68(%rsp)
jmp 0xc14a
movq 0x68(%rsp), %rdi
movq 0x2d0(%rsp), %rsi
callq 0x8440
movq %rax, 0x60(%rsp)
jmp 0xc163
movq 0x60(%rsp), %rdi
movq 0xcdde9(%rip), %rsi     # 0xd9f58
callq 0x8480
jmp 0xc176
movq 0x190(%rsp), %rdi
movq 0x2d8(%rsp), %rsi
callq 0x8210
movaps %xmm0, %xmm1
cvttsd2si %xmm1, %rax
movq %rax, %rdx
sarq $0x3f, %rdx
movsd 0x9ce66(%rip), %xmm1    # 0xa9008
subsd %xmm1, %xmm0
cvttsd2si %xmm0, %rcx
andq %rdx, %rcx
orq %rcx, %rax
movq %rax, 0x188(%rsp)
movq 0xcddd8(%rip), %rdi     # 0xd9f98
leaq 0x9d290(%rip), %rsi     # 0xa9457
callq 0x8440
movq %rax, 0x58(%rsp)
jmp 0xc1d3
movq 0x58(%rsp), %rdi
movq 0x188(%rsp), %rax
shrq $0x4, %rax
movabsq $0x91a2b3c4d5e6f81, %rcx # imm = 0x91A2B3C4D5E6F81
mulq %rcx
movq %rdx, %rsi
shrq $0x3, %rsi
callq 0x8100
movq %rax, 0x50(%rsp)
jmp 0xc204
movq 0x50(%rsp), %rdi
leaq 0x9e6dd(%rip), %rsi     # 0xaa8ed
callq 0x8440
movq %rax, 0x48(%rsp)
jmp 0xc21c
movq 0x48(%rsp), %rdi
movq 0x188(%rsp), %rax
movq %rax, 0x38(%rsp)
shrq $0x4, %rax
movabsq $0x91a2b3c4d5e6f81, %rcx # imm = 0x91A2B3C4D5E6F81
mulq %rcx
movq 0x38(%rsp), %rax
shrq $0x3, %rdx
imulq $0xe10, %rdx, %rcx      # imm = 0xE10
subq %rcx, %rax
movabsq $0x444444444444445, %rcx # imm = 0x444444444444445
mulq %rcx
movq %rdx, %rsi
callq 0x8100
movq %rax, 0x40(%rsp)
jmp 0xc26e
movq 0x40(%rsp), %rdi
leaq 0x9e673(%rip), %rsi     # 0xaa8ed
callq 0x8440
movq %rax, 0x30(%rsp)
jmp 0xc286
movq 0x30(%rsp), %rdi
movq 0x188(%rsp), %rsi
movq %rsi, %rax
shrq $0x4, %rax
movabsq $0x91a2b3c4d5e6f81, %rcx # imm = 0x91A2B3C4D5E6F81
mulq %rcx
shrq $0x3, %rdx
imulq $0xe10, %rdx, %rax      # imm = 0xE10
subq %rax, %rsi
movabsq $0x444444444444445, %rcx # imm = 0x444444444444445
movq %rsi, %rax
mulq %rcx
imulq $0x3c, %rdx, %rax
subq %rax, %rsi
callq 0x8100
movq %rax, 0x28(%rsp)
jmp 0xc2d8
movq 0x28(%rsp), %rdi
movq 0xcdc74(%rip), %rsi     # 0xd9f58
callq 0x8480
jmp 0xc2eb
movq 0xcdca6(%rip), %rdi     # 0xd9f98
leaq 0x9f786(%rip), %rsi     # 0xaba7f
callq 0x8440
movq %rax, 0x20(%rsp)
jmp 0xc305
movq 0x20(%rsp), %rdi
movq 0xcdc47(%rip), %rsi     # 0xd9f58
callq 0x8480
jmp 0xc318
movq 0xcdc79(%rip), %rdi     # 0xd9f98
leaq 0x9d149(%rip), %rsi     # 0xa946f
callq 0x8440
movq %rax, 0x18(%rsp)
jmp 0xc332
movq 0x18(%rsp), %rdi
movq 0xcdc1a(%rip), %rsi     # 0xd9f58
callq 0x8480
jmp 0xc345
leaq 0x9d148(%rip), %rsi     # 0xa9494
leaq 0x358(%rsp), %rdi
movq %rdi, 0x10(%rsp)
movq $-0x1, %rdx
callq 0x8420
movq 0x10(%rsp), %rsi
movq %rax, %rcx
xorl %eax, %eax
movl %eax, %edx
leaq 0x108(%rsp), %rdi
callq 0x8460
jmp 0xc380
leaq 0x9d10f(%rip), %rdx     # 0xa9496
leaq 0x128(%rsp), %rdi
leaq 0x108(%rsp), %rsi
callq 0xd060
jmp 0xc39e
movl 0x2f4(%rsp), %esi
leaq 0xe8(%rsp), %rdi
callq 0xd1a0
jmp 0xc3b4
leaq 0x148(%rsp), %rdi
leaq 0x128(%rsp), %rsi
leaq 0xe8(%rsp), %rdx
callq 0xd0b0
jmp 0xc3d3
leaq 0x9d0c7(%rip), %rdx     # 0xa94a1
leaq 0x168(%rsp), %rdi
leaq 0x148(%rsp), %rsi
callq 0xd060
jmp 0xc3f1
leaq 0x168(%rsp), %rdi
callq 0x8190
movq %rax, %rdx
leaq 0x238(%rsp), %rdi
leaq 0x198(%rsp), %rsi
callq 0xb540
jmp 0xc418
leaq 0x168(%rsp), %rdi
callq 0x8848
leaq 0x148(%rsp), %rdi
callq 0x8848
leaq 0xe8(%rsp), %rdi
callq 0x8848
leaq 0x128(%rsp), %rdi
callq 0x8848
leaq 0x108(%rsp), %rdi
callq 0x8848
leaq 0x198(%rsp), %rdi
callq 0x1f290
leaq 0x238(%rsp), %rdi
callq 0x2c6d0
leaq 0x2e8(%rsp), %rdi
xorl %esi, %esi
callq 0xd2e0
movq %rax, 0xe0(%rsp)
movl 0x2f4(%rsp), %eax
addl $0x1, %eax
movl %eax, 0x2f4(%rsp)
jmp 0xbd96
movq %rax, %rcx
movl %edx, %eax
movq %rcx, 0x350(%rsp)
movl %eax, 0x34c(%rsp)
jmp 0xc58f
movq %rax, %rcx
movl %edx, %eax
movq %rcx, 0x350(%rsp)
movl %eax, 0x34c(%rsp)
jmp 0xc582
movq %rax, %rcx
movl %edx, %eax
movq %rcx, 0x350(%rsp)
movl %eax, 0x34c(%rsp)
jmp 0xc575
movq %rax, %rcx
movl %edx, %eax
movq %rcx, 0x350(%rsp)
movl %eax, 0x34c(%rsp)
jmp 0xc568
movq %rax, %rcx
movl %edx, %eax
movq %rcx, 0x350(%rsp)
movl %eax, 0x34c(%rsp)
jmp 0xc55b
movq %rax, %rcx
movl %edx, %eax
movq %rcx, 0x350(%rsp)
movl %eax, 0x34c(%rsp)
jmp 0xc54e
movq %rax, %rcx
movl %edx, %eax
movq %rcx, 0x350(%rsp)
movl %eax, 0x34c(%rsp)
leaq 0x168(%rsp), %rdi
callq 0x8848
leaq 0x148(%rsp), %rdi
callq 0x8848
leaq 0xe8(%rsp), %rdi
callq 0x8848
leaq 0x128(%rsp), %rdi
callq 0x8848
leaq 0x108(%rsp), %rdi
callq 0x8848
leaq 0x198(%rsp), %rdi
callq 0x1f290
leaq 0x238(%rsp), %rdi
callq 0x2c6d0
jmp 0xc618
movq 0xcd9f3(%rip), %rdi     # 0xd9f98
leaq 0x9cefa(%rip), %rsi     # 0xa94a6
callq 0x8440
movq %rax, 0x8(%rsp)
jmp 0xc5b8
movq 0x8(%rsp), %rdi
movq 0xcd994(%rip), %rsi     # 0xd9f58
callq 0x8480
jmp 0xc5cb
movq 0xcd9fe(%rip), %rdi     # 0xd9fd0
callq 0x84f0
jmp 0xc5d9
movl $0x0, 0x3a4(%rsp)
movl $0x1, 0x348(%rsp)
leaq 0x358(%rsp), %rdi
callq 0x8848
leaq 0x378(%rsp), %rdi
callq 0x8848
movl 0x3a4(%rsp), %eax
addq $0x3a8, %rsp            # imm = 0x3A8
retq
leaq 0x358(%rsp), %rdi
callq 0x8848
leaq 0x378(%rsp), %rdi
callq 0x8848
movq 0x350(%rsp), %rdi
callq 0x8770
nop