// File: gvaumour[P]cache-simulator/src/Perceptron.cc
// Function: PerceptronPredictor::allocateInNVM(unsigned long, Access)
allocDecision
PerceptronPredictor::allocateInNVM(uint64_t set, Access element)
{
//	if(element.isInstFetch())
//		return ALLOCATE_IN_NVM;
	
	update_globalPChistory(element.m_pc);
	stats_nbMiss++;
	miss_counter++;
	if(miss_counter > 255)
		miss_counter = 255;
	
	// All the set is a learning/sampled set independantly of its way or SRAM/NVM alloc
	bool isLearning = m_tableSRAM[set][0]->isLearning; 
	
	if(!isLearning && m_enableBP)
	{
		//Predict if we should bypass
		int sum_prediction = 0;
		vector<double> samples;
		for(unsigned i = 0 ; i < m_BP_features.size(); i++)
		{
			int hash = m_BP_features_hash[i](element.m_address , element.m_pc);
			int pred = m_BP_features[i]->getConfidence(hash,true);
			samples.push_back(pred);
			sum_prediction += pred;
		}

		if(simu_parameters.perceptron_compute_variance)
		{	//Compute Variance of the sample
			double variance = 0, avg = (double)sum_prediction / (double) samples.size();
			for(unsigned i = 0 ; i < samples.size(); i++)
				variance += (samples[i] - avg) * (samples[i] - avg);

			variance = sqrt( variance / (double) samples.size());
			stats_variances_buffer.push_back(variance);
		}		
		
		if(sum_prediction > simu_parameters.perceptron_bypass_threshold)
		{
			stats_nbBPrequests[stats_nbBPrequests.size()-1]++;
			return BYPASS_CACHE;
		}
	}

	if(m_enableAllocation)
	{
		//Bypass decision is done, we do not bypass
		//Decide NVM/SRAM allocation
		int sum_prediction = 0;
		for(unsigned i = 0 ; i < m_Allocation_features.size(); i++)
		{
			int hash = m_Allocation_features_hash[i](element.m_address , element.m_pc);
			int pred = m_Allocation_features[i]->getConfidence(hash, true);
			sum_prediction += pred;
		}	
	
		if(sum_prediction > simu_parameters.perceptron_allocation_threshold)
			return ALLOCATE_IN_NVM;
		else
			return ALLOCATE_IN_SRAM;
	}
	else 
		return ALLOCATE_IN_SRAM;
}

// Assembly:
subq $0xd8, %rsp
leaq 0xe0(%rsp), %rax
movq %rax, 0x48(%rsp)
movq %rdi, 0xc8(%rsp)
movq %rsi, 0xc0(%rsp)
movq 0xc8(%rsp), %rdi
movq %rdi, 0x50(%rsp)
movq 0x10(%rax), %rsi
callq 0x51630
movq 0x50(%rsp), %rax
movq 0x398(%rax), %rcx
addq $0x1, %rcx
movq %rcx, 0x398(%rax)
leaq 0x430e8(%rip), %rax     # 0x94240
movl (%rax), %ecx
addl $0x1, %ecx
leaq 0x430dc(%rip), %rax     # 0x94240
movl %ecx, (%rax)
leaq 0x430d3(%rip), %rax     # 0x94240
cmpl $0xff, (%rax)
jle 0x51182
leaq 0x430c4(%rip), %rax     # 0x94240
movl $0xff, (%rax)
movq 0x50(%rsp), %rax
movq 0x8(%rax), %rdi
movq 0xc0(%rsp), %rsi
callq 0xf9a0
movq %rax, %rdi
xorl %eax, %eax
movl %eax, %esi
callq 0xf9c0
movq (%rax), %rax
movb 0x148(%rax), %al
andb $0x1, %al
movb %al, 0xbf(%rsp)
testb $0x1, 0xbf(%rsp)
jne 0x5151b
movq 0x50(%rsp), %rax
testb $0x1, 0x348(%rax)
je 0x5151b
movl $0x0, 0xb8(%rsp)
leaq 0xa0(%rsp), %rdi
callq 0xe8e0
movl $0x0, 0x9c(%rsp)
movq 0x50(%rsp), %rdi
movl 0x9c(%rsp), %eax
movq %rax, 0x40(%rsp)
addq $0x2b8, %rdi            # imm = 0x2B8
callq 0xf840
movq %rax, %rcx
movq 0x40(%rsp), %rax
cmpq %rcx, %rax
jae 0x5131c
movq 0x50(%rsp), %rdi
addq $0x2d0, %rdi            # imm = 0x2D0
movl 0x9c(%rsp), %eax
movl %eax, %esi
callq 0x4d780
movq 0x48(%rsp), %rcx
movq (%rax), %rax
movq (%rcx), %rdi
movq 0x10(%rcx), %rsi
callq *%rax
movl %eax, 0x3c(%rsp)
jmp 0x51258
movq 0x50(%rsp), %rdi
movl 0x3c(%rsp), %eax
movl %eax, 0x98(%rsp)
addq $0x2b8, %rdi            # imm = 0x2B8
movl 0x9c(%rsp), %eax
movl %eax, %esi
callq 0xf8c0
movq (%rax), %rdi
movl 0x98(%rsp), %esi
movl $0x1, %edx
callq 0x2d520
movl %eax, 0x38(%rsp)
jmp 0x51297
movl 0x38(%rsp), %eax
movl %eax, 0x88(%rsp)
cvtsi2sdl 0x88(%rsp), %xmm0
movsd %xmm0, 0x80(%rsp)
leaq 0xa0(%rsp), %rdi
leaq 0x80(%rsp), %rsi
callq 0x20dc0
jmp 0x512cb
movl 0x88(%rsp), %eax
addl 0xb8(%rsp), %eax
movl %eax, 0xb8(%rsp)
movl 0x9c(%rsp), %eax
addl $0x1, %eax
movl %eax, 0x9c(%rsp)
jmp 0x511f9
movq %rax, %rcx
movl %edx, %eax
movq %rcx, 0x90(%rsp)
movl %eax, 0x8c(%rsp)
leaq 0xa0(%rsp), %rdi
callq 0xf460
jmp 0x5161f
leaq 0x42ccd(%rip), %rax     # 0x93ff0
testb $0x1, 0x1cd(%rax)
je 0x51490
movq $0x0, 0x78(%rsp)
cvtsi2sdl 0xb8(%rsp), %xmm0
movsd %xmm0, 0x30(%rsp)
leaq 0xa0(%rsp), %rdi
callq 0xfbe0
movsd 0x30(%rsp), %xmm0
movq %rax, %xmm1
movaps 0x1fca9(%rip), %xmm2    # 0x71010
punpckldq %xmm2, %xmm1    # xmm1 = xmm1[0],xmm2[0],xmm1[1],xmm2[1]
movapd 0x1fcad(%rip), %xmm2    # 0x71020
subpd %xmm2, %xmm1
movaps %xmm1, %xmm2
unpckhpd %xmm1, %xmm1            # xmm1 = xmm1[1,1]
addsd %xmm2, %xmm1
divsd %xmm1, %xmm0
movsd %xmm0, 0x70(%rsp)
movl $0x0, 0x6c(%rsp)
movl 0x6c(%rsp), %eax
movq %rax, 0x28(%rsp)
leaq 0xa0(%rsp), %rdi
callq 0xfbe0
movq %rax, %rcx
movq 0x28(%rsp), %rax
cmpq %rcx, %rax
jae 0x51421
movl 0x6c(%rsp), %eax
movl %eax, %esi
leaq 0xa0(%rsp), %rdi
callq 0xfc00
movsd (%rax), %xmm0
subsd 0x70(%rsp), %xmm0
movsd %xmm0, 0x20(%rsp)
movl 0x6c(%rsp), %eax
movl %eax, %esi
leaq 0xa0(%rsp), %rdi
callq 0xfc00
movsd 0x20(%rsp), %xmm0
movsd (%rax), %xmm2
subsd 0x70(%rsp), %xmm2
movsd 0x78(%rsp), %xmm1
mulsd %xmm2, %xmm0
addsd %xmm1, %xmm0
movsd %xmm0, 0x78(%rsp)
movl 0x6c(%rsp), %eax
addl $0x1, %eax
movl %eax, 0x6c(%rsp)
jmp 0x51394
movsd 0x78(%rsp), %xmm0
movsd %xmm0, 0x18(%rsp)
leaq 0xa0(%rsp), %rdi
callq 0xfbe0
movsd 0x18(%rsp), %xmm0
movq %rax, %xmm1
movaps 0x1fbc4(%rip), %xmm2    # 0x71010
punpckldq %xmm2, %xmm1    # xmm1 = xmm1[0],xmm2[0],xmm1[1],xmm2[1]
movapd 0x1fbc8(%rip), %xmm2    # 0x71020
subpd %xmm2, %xmm1
movaps %xmm1, %xmm2
unpckhpd %xmm1, %xmm1            # xmm1 = xmm1[1,1]
addsd %xmm2, %xmm1
divsd %xmm1, %xmm0
callq 0x52e0
movq 0x50(%rsp), %rdi
movsd %xmm0, 0x78(%rsp)
addq $0x3a8, %rdi            # imm = 0x3A8
leaq 0x78(%rsp), %rsi
callq 0xfc20
jmp 0x5148e
jmp 0x51490
movl 0xb8(%rsp), %eax
leaq 0x42b52(%rip), %rcx     # 0x93ff0
cmpl 0x1b8(%rcx), %eax
jle 0x514f5
movq 0x50(%rsp), %rdi
movq %rdi, %rax
addq $0x350, %rax            # imm = 0x350
movq %rax, 0x10(%rsp)
addq $0x350, %rdi            # imm = 0x350
callq 0xfa40
movq 0x10(%rsp), %rdi
movq %rax, %rsi
subq $0x1, %rsi
callq 0xfa20
movq (%rax), %rcx
addq $0x1, %rcx
movq %rcx, (%rax)
movl $0x2, 0xd4(%rsp)
movl $0x1, 0x68(%rsp)
jmp 0x514fd
movl $0x0, 0x68(%rsp)
leaq 0xa0(%rsp), %rdi
callq 0xf460
movl 0x68(%rsp), %eax
testl %eax, %eax
je 0x51519
jmp 0x51514
jmp 0x51610
jmp 0x5151b
movq 0x50(%rsp), %rax
testb $0x1, 0x349(%rax)
je 0x51605
movl $0x0, 0x64(%rsp)
movl $0x0, 0x60(%rsp)
movq 0x50(%rsp), %rdi
movl 0x60(%rsp), %eax
movq %rax, 0x8(%rsp)
addq $0x270, %rdi            # imm = 0x270
callq 0xf840
movq %rax, %rcx
movq 0x8(%rsp), %rax
cmpq %rcx, %rax
jae 0x515d8
movq 0x50(%rsp), %rdi
addq $0x288, %rdi            # imm = 0x288
movl 0x60(%rsp), %eax
movl %eax, %esi
callq 0x4d780
movq 0x48(%rsp), %rcx
movq (%rax), %rax
movq (%rcx), %rdi
movq 0x10(%rcx), %rsi
callq *%rax
movq 0x50(%rsp), %rdi
movl %eax, 0x5c(%rsp)
addq $0x270, %rdi            # imm = 0x270
movl 0x60(%rsp), %eax
movl %eax, %esi
callq 0xf8c0
movq (%rax), %rdi
movl 0x5c(%rsp), %esi
movl $0x1, %edx
callq 0x2d520
movl %eax, 0x58(%rsp)
movl 0x58(%rsp), %eax
addl 0x64(%rsp), %eax
movl %eax, 0x64(%rsp)
movl 0x60(%rsp), %eax
addl $0x1, %eax
movl %eax, 0x60(%rsp)
jmp 0x5153d
movl 0x64(%rsp), %eax
leaq 0x42a0d(%rip), %rcx     # 0x93ff0
cmpl 0x1c0(%rcx), %eax
jle 0x515f8
movl $0x1, 0xd4(%rsp)
jmp 0x51610
movl $0x0, 0xd4(%rsp)
jmp 0x51610
movl $0x0, 0xd4(%rsp)
movl 0xd4(%rsp), %eax
addq $0xd8, %rsp
retq
movq 0x90(%rsp), %rdi
callq 0x5690
nopl (%rax)