// File: /workspace/github_cpp_makefile_star2_O2/narges64[P]SIMBA/ssd.cpp
// Function: print_statistics(ssd_info*, int)
void print_statistics(ssd_info *ssd, int app){

	fprintf(ssd->statisticfile, "======== Application %d , time %lld ============ \n", app, ssd->total_execution_time);

	fprintf(ssd->statisticfile, "request read RT avg %lld us , var %lld ms2 , count %lld , max %lld us\n", 
									ssd->stats->read_RT.get_average(), ssd->stats->read_RT.get_variance(), 
									ssd->stats->read_RT.get_count() , ssd->stats->read_RT.get_max());

	fprintf(ssd->statisticfile, "request write RT avg %lld us , var %lld ms2, count %lld , max %lld us \n", 
									ssd->stats->write_RT.get_average(), ssd->stats->write_RT.get_variance(), 
									ssd->stats->write_RT.get_count() , ssd->stats->write_RT.get_max());
	
	fprintf(ssd->statisticfile, "read IOPS and BW [%d]: %f , %f  \n", app, ssd->stats->read_throughput.get_IOPS() , ssd->stats->read_throughput.get_BW());
	fprintf(ssd->statisticfile, "write IOPS and BW [%d]: %f , %f  \n", app, ssd->stats->write_throughput.get_IOPS() , ssd->stats->write_throughput.get_BW());

	fprintf(ssd->statisticfile,"erase: ( %lld )\n", ssd->stats->total_flash_erase_count);
	fprintf(ssd->statisticfile,"total gc move count: %d \n", ssd->stats->gc_moved_page);
	fprintf(ssd->statisticfile, "buffer read hit %d , write hit %d , gc buffer read hit %d , write hit %d \n ", 
								ssd->dram->buffer->read_hit , ssd->dram->buffer->write_hit , 
								ssd->dram->gc_buffer->read_hit , ssd->dram->gc_buffer->write_hit); 

	fprintf(ssd->statisticfile, "flash program count %d , WAF %f\n" , ssd->stats->flash_prog_count , (ssd->stats->flash_prog_count)/(double)(ssd->stats->flash_prog_count - ssd->stats->gc_moved_page));  

	fprintf(ssd->statisticfile, "========================\n");

	ssd->stats->flash_erase_count = 0;

	// Print lun statistic output
	int chan,lun = 0;
	/*


	fprintf(ssd->statisticfile, "\nlun IOPS \n");
	for (chan = 0; chan < ssd->parameter->channel_number; chan++){
		for (lun = 0; lun < ssd->channel_head[chan]->lun_num; lun++){
			fprintf(ssd->statisticfile, "%d,", (int)ssd->channel_head[chan]->lun_head[lun]->stat_read_throughput.get_IOPS());
			fprintf(ssd->statisticfile, "%d,", (int)ssd->channel_head[chan]->lun_head[lun]->stat_write_throughput.get_IOPS());
			fprintf(ssd->statisticfile, "%d\t", (int)ssd->channel_head[chan]->lun_head[lun]->stat_rw_throughput.get_IOPS());
		}
		fprintf(ssd->statisticfile, "\n");
	}

	fprintf(ssd->statisticfile, "\nlun BW  (MB/s) \n");
	for (chan = 0; chan < ssd->parameter->channel_number; chan++){
		for (lun = 0; lun < ssd->channel_head[chan]->lun_num; lun++){
			fprintf(ssd->statisticfile, "%d,", (int)ssd->channel_head[chan]->lun_head[lun]->stat_read_throughput.get_BW());
			fprintf(ssd->statisticfile, "%d,", (int)ssd->channel_head[chan]->lun_head[lun]->stat_write_throughput.get_BW());
			fprintf(ssd->statisticfile, "%d\t", (int)ssd->channel_head[chan]->lun_head[lun]->stat_rw_throughput.get_BW());
		}
		fprintf(ssd->statisticfile, "\n");
	}

	fprintf(ssd->statisticfile, "\nlun noop IOPS \n");
	for (chan = 0; chan < ssd->parameter->channel_number; chan++){
		for (lun = 0; lun < ssd->channel_head[chan]->lun_num; lun++){
			fprintf(ssd->statisticfile, "%d,", (int)ssd->channel_head[chan]->lun_head[lun]->stat_read_throughput.get_noop_IOPS());
			fprintf(ssd->statisticfile, "%d,", (int)ssd->channel_head[chan]->lun_head[lun]->stat_write_throughput.get_noop_IOPS());
			fprintf(ssd->statisticfile, "%d\t", (int)ssd->channel_head[chan]->lun_head[lun]->stat_rw_throughput.get_noop_IOPS());
		}
		fprintf(ssd->statisticfile, "\n");
	}


	fprintf(ssd->statisticfile, "\nlun noop BW (MB/s) \n");
	for (chan = 0; chan < ssd->parameter->channel_number; chan++){
		for (lun = 0; lun < ssd->channel_head[chan]->lun_num; lun++){
			fprintf(ssd->statisticfile, "%d,", (int)ssd->channel_head[chan]->lun_head[lun]->stat_read_throughput.get_noop_BW());
			fprintf(ssd->statisticfile, "%d,", (int)ssd->channel_head[chan]->lun_head[lun]->stat_write_throughput.get_noop_BW());
			fprintf(ssd->statisticfile, "%d\t", (int)ssd->channel_head[chan]->lun_head[lun]->stat_rw_throughput.get_noop_BW());
		}
		fprintf(ssd->statisticfile, "\n");
	}
	*/

	fprintf(ssd->statisticfile, "\nlun erase count \n");
	for (chan = 0; chan < ssd->parameter->channel_number; chan++){
		for (lun = 0; lun < ssd->channel_head[chan]->lun_num; lun++){
			fprintf(ssd->statisticfile, "%d\t", ssd->channel_head[chan]->lun_head[lun]->erase_count);
		}
		fprintf(ssd->statisticfile, "\n");
	}

	fprintf(ssd->statisticfile, "\nplanes erase number: \n");
	for(int i=0;i<ssd->parameter->channel_number;i++){
		for (int j = 0; j < ssd->parameter->lun_channel[i]; j++){
			for(int l=0;l<ssd->parameter->plane_lun;l++)
			{
				int plane_erase = ssd->channel_head[i]->lun_head[j]->plane_head[l]->erase_count;
				fprintf(ssd->statisticfile,"(%d,%d)",l, plane_erase);
			}
			fprintf(ssd->statisticfile, "\t");
		}
		fprintf(ssd->statisticfile, "\n");
	}

}

// Assembly:
pushq %rbp
pushq %r15
pushq %r14
pushq %r13
pushq %r12
pushq %rbx
pushq %rax
movl %esi, %ebp
movq %rdi, %rbx
movq 0x28(%rdi), %rcx
movq 0x50(%rdi), %rdi
leaq 0x24a0(%rip), %rsi      # 0x9d4e
xorl %r15d, %r15d
movl %ebp, %edx
xorl %eax, %eax
callq 0x2250
movq 0x50(%rbx), %r12
movq 0x98(%rbx), %rax
leaq 0x8(%rax), %rdi
movslq 0x8(%rax), %rcx
testq %rcx, %rcx
je 0x78de
movq 0x10(%rax), %rax
cqto
idivq %rcx
movq %rax, %r15
callq 0x8914
movq 0x98(%rbx), %rcx
movl 0x8(%rcx), %r8d
movq 0x20(%rcx), %r9
leaq 0x2488(%rip), %rsi      # 0x9d81
xorl %r14d, %r14d
movq %r12, %rdi
movq %r15, %rdx
movq %rax, %rcx
xorl %eax, %eax
callq 0x2250
movq 0x50(%rbx), %r15
movq 0x98(%rbx), %rax
leaq 0x30(%rax), %rdi
movslq 0x30(%rax), %rcx
testq %rcx, %rcx
je 0x7930
movq 0x38(%rax), %rax
cqto
idivq %rcx
movq %rax, %r14
callq 0x8914
movq 0x98(%rbx), %rcx
movl 0x30(%rcx), %r8d
movq 0x48(%rcx), %r9
leaq 0x247d(%rip), %rsi      # 0x9dc8
movq %r15, %rdi
movq %r14, %rdx
movq %rax, %rcx
xorl %eax, %eax
callq 0x2250
movq 0x50(%rbx), %r14
movl $0x190, %r15d           # imm = 0x190
movq 0x98(%rbx), %rdi
addq %r15, %rdi
callq 0x8954
movsd %xmm0, (%rsp)
addq 0x98(%rbx), %r15
movq %r15, %rdi
callq 0x8978
movaps %xmm0, %xmm1
leaq 0x247e(%rip), %rsi      # 0x9e10
movq %r14, %rdi
movl %ebp, %edx
movsd (%rsp), %xmm0
movb $0x2, %al
callq 0x2250
movq 0x50(%rbx), %r14
movl $0x1b0, %r15d           # imm = 0x1B0
movq 0x98(%rbx), %rdi
addq %r15, %rdi
callq 0x8954
movsd %xmm0, (%rsp)
addq 0x98(%rbx), %r15
movq %r15, %rdi
callq 0x8978
movaps %xmm0, %xmm1
leaq 0x2458(%rip), %rsi      # 0x9e32
movq %r14, %rdi
movl %ebp, %edx
movsd (%rsp), %xmm0
movb $0x2, %al
callq 0x2250
movq 0x50(%rbx), %rdi
movq 0x98(%rbx), %rax
movq 0xa0(%rax), %rdx
leaq 0x2451(%rip), %rsi      # 0x9e55
xorl %eax, %eax
callq 0x2250
movq 0x50(%rbx), %rdi
movq 0x98(%rbx), %rax
movl 0xc8(%rax), %edx
leaq 0x2443(%rip), %rsi      # 0x9e66
xorl %eax, %eax
callq 0x2250
movq 0x50(%rbx), %rdi
movq 0x60(%rbx), %rax
movq 0x18(%rax), %rcx
movq 0x20(%rax), %rax
movl (%rcx), %edx
movl 0x4(%rcx), %ecx
movl (%rax), %r8d
movl 0x4(%rax), %r9d
leaq 0x2433(%rip), %rsi      # 0x9e80
xorl %eax, %eax
callq 0x2250
movq 0x50(%rbx), %rdi
movq 0x98(%rbx), %rax
movq 0x88(%rax), %rdx
cvtsi2sd %rdx, %xmm0
movslq 0xc8(%rax), %rax
movq %rdx, %rcx
subq %rax, %rcx
cvtsi2sd %rcx, %xmm1
divsd %xmm1, %xmm0
leaq 0x2444(%rip), %rsi      # 0x9ecc
movb $0x1, %al
callq 0x2250
movq 0x50(%rbx), %rcx
leaq 0x2453(%rip), %rdi      # 0x9eed
pushq $0x19
popq %rsi
pushq $0x1
popq %r14
movq %r14, %rdx
callq 0x22e0
movq 0x98(%rbx), %rax
andq $0x0, 0x98(%rax)
movq 0x50(%rbx), %rcx
leaq 0x2444(%rip), %rdi      # 0x9f07
pushq $0x12
popq %rsi
movq %r14, %rdx
callq 0x22e0
leaq 0x2445(%rip), %r14      # 0x9f1a
pushq $0xa
popq %rbp
xorl %r15d, %r15d
movq 0x58(%rbx), %rax
movl 0x98(%rax), %eax
cmpq %rax, %r15
jae 0x7b2d
xorl %r12d, %r12d
movq 0x50(%rbx), %rsi
movq 0x90(%rbx), %rax
movq (%rax,%r15,8), %rax
movslq (%rax), %rcx
cmpq %rcx, %r12
jge 0x7b21
movq 0x50(%rax), %rax
movq (%rax,%r12,8), %rax
movl 0x8(%rax), %edx
movq %rsi, %rdi
movq %r14, %rsi
xorl %eax, %eax
callq 0x2250
incq %r12
jmp 0x7aed
movl %ebp, %edi
callq 0x21f0
incq %r15
jmp 0x7adb
movq 0x50(%rbx), %rcx
leaq 0x23e6(%rip), %rdi      # 0x9f1e
pushq $0x17
popq %rsi
pushq $0x1
popq %rdx
callq 0x22e0
leaq 0x23ec(%rip), %r14      # 0x9f36
pushq $0x9
popq %rbp
xorl %r13d, %r13d
movq 0x58(%rbx), %rax
movl 0x98(%rax), %ecx
cmpq %rcx, %r13
jae 0x7bdc
xorl %r15d, %r15d
movl 0x9c(%rax,%r13,4), %ecx
cmpq %rcx, %r15
jae 0x7bc8
xorl %r12d, %r12d
movl 0x22c(%rax), %eax
cmpq %rax, %r12
jae 0x7bb4
movq 0x50(%rbx), %rdi
movq 0x90(%rbx), %rax
movq (%rax,%r13,8), %rax
movq 0x50(%rax), %rax
movq (%rax,%r15,8), %rax
movq (%rax), %rax
movq (%rax,%r12,8), %rax
movl 0x30(%rax), %ecx
movq %r14, %rsi
movl %r12d, %edx
xorl %eax, %eax
callq 0x2250
incq %r12
movq 0x58(%rbx), %rax
jmp 0x7b72
movq 0x50(%rbx), %rsi
movl %ebp, %edi
callq 0x21f0
incq %r15
movq 0x58(%rbx), %rax
jmp 0x7b62
movq 0x50(%rbx), %rsi
pushq $0xa
popq %rdi
callq 0x21f0
incq %r13
jmp 0x7b50
addq $0x8, %rsp
popq %rbx
popq %r12
popq %r13
popq %r14
popq %r15
popq %rbp
retq