// File: gvaumour[P]cache-simulator/src/Cerebron.cc
// Function: CerebronPredictor::evictPolicy(int, bool)
int CerebronPredictor::evictPolicy(int set, bool inNVM)
{
	int assoc_victim = -1;
	assert(m_replacementPolicyNVM_ptr != NULL);
	assert(m_replacementPolicySRAM_ptr != NULL);

	CacheEntry* entry = NULL;
	if(inNVM)
	{	
		assoc_victim = m_replacementPolicyNVM_ptr->evictPolicy(set);
		entry = m_tableNVM[set][assoc_victim];
	}
	else
	{
		assoc_victim = m_replacementPolicySRAM_ptr->evictPolicy(set);
		entry = m_tableSRAM[set][assoc_victim];		
	}

	if(!entry->isValid)
		return assoc_victim;

	allocDecision des = getDecision(entry);
	if(simu_parameters.perceptron_drawFeatureMaps)
	{
		bool global_error = false;
		
		if(( des == ALLOCATE_IN_SRAM && inNVM ) || \
			( des == ALLOCATE_IN_NVM && !inNVM ))
			global_error = true;

		int hash1 = hashing_function1(m_features_hash[0] , entry->address , entry->missPC);
		int hash2 = (m_features.size() > 1) ? hashing_function1(m_features_hash[1], entry->address , entry->missPC) : 0;
		if(global_error)
			stats_global_error[hash1][hash2].first++;
		else
			stats_global_error[hash1][hash2].second++;
		
	
		for(unsigned i = 0; i < m_features.size() ; i++)
		{
			int hash = hashing_function1( m_features_hash[i] , entry->address , entry->missPC);

			bool local_error = false;
			if( des == ALLOCATE_IN_NVM && entry->PHC_allocation_pred[i].second == ALLOCATE_IN_SRAM)
				local_error = true;
			else if(  des == ALLOCATE_IN_SRAM && entry->PHC_allocation_pred[i].second == ALLOCATE_IN_NVM )
			 	local_error = true;
			 					
			if(local_error)	
				stats_local_error[i][hash].first++;
			else 
				stats_local_error[i][hash].second++;
				
		}

	}
		
	if( (des == ALLOCATE_IN_NVM && !inNVM) || \
		(des == ALLOCATE_IN_SRAM && inNVM) )
	{
		if(simu_parameters.printDebug)
		{
			string a = inNVM ? "NVM" : "SRAM"; 
			debug_file << cpt_time << ": Eviction of 0x" << std::hex  << entry->address \
				   << std::dec << " , wrongly allocated in " << a << ", cost=" << entry->cost_value << endl;
			
			for(unsigned i = 0; i < m_features.size() ; i++)
			{
				int hash = hashing_function1( m_features_hash[i] , entry->address , entry->missPC);
				int confidence = m_features[i]->getConfidence(hash, false);
				allocDecision des = m_features[i]->getAllocDecision(hash, false);
				debug_file << "\t-Feature " << i << "\t" << str_allocDecision[des] << "\t" << confidence << endl;
			}
		}
		
		stats_wrong_alloc++;
	}
	else
		stats_good_alloc++;
		
	/* Trigger the learning process */ 
	if( entry->isLearning_weight && !simu_parameters.Cerebron_fastlearning)
		doLearning(entry, inNVM);
	

	if(entry->nbWrite == 0 && entry->nbRead == 0)
		stats_nbDeadLine[stats_nbDeadLine.size()-1]++;

	evictRecording(set , assoc_victim , inNVM);	
	return assoc_victim;
}

// Assembly:
subq $0x228, %rsp            # imm = 0x228
movb %dl, %al
movq %rdi, 0x218(%rsp)
movl %esi, 0x214(%rsp)
andb $0x1, %al
movb %al, 0x213(%rsp)
movq 0x218(%rsp), %rax
movq %rax, 0xe8(%rsp)
movl $0xffffffff, 0x20c(%rsp) # imm = 0xFFFFFFFF
cmpq $0x0, 0x60(%rax)
je 0xb535
jmp 0xb554
leaq 0x65c65(%rip), %rdi     # 0x711a1
leaq 0x65b4c(%rip), %rsi     # 0x7108f
movl $0xf0, %edx
leaq 0x65c75(%rip), %rcx     # 0x711c4
callq 0x5260
movq 0xe8(%rsp), %rax
cmpq $0x0, 0x68(%rax)
je 0xb565
jmp 0xb584
leaq 0x65c8e(%rip), %rdi     # 0x711fa
leaq 0x65b1c(%rip), %rsi     # 0x7108f
movl $0xf1, %edx
leaq 0x65c45(%rip), %rcx     # 0x711c4
callq 0x5260
movq $0x0, 0x200(%rsp)
testb $0x1, 0x213(%rsp)
je 0xb5f2
movq 0xe8(%rsp), %rax
movq 0x60(%rax), %rdi
movl 0x214(%rsp), %esi
movq (%rdi), %rax
callq *0x20(%rax)
movl %eax, %ecx
movq 0xe8(%rsp), %rax
movl %ecx, 0x20c(%rsp)
movq 0x10(%rax), %rdi
movslq 0x214(%rsp), %rsi
callq 0xf9a0
movq %rax, %rdi
movslq 0x20c(%rsp), %rsi
callq 0xf9c0
movq (%rax), %rax
movq %rax, 0x200(%rsp)
jmp 0xb648
movq 0xe8(%rsp), %rax
movq 0x68(%rax), %rdi
movl 0x214(%rsp), %esi
movq (%rdi), %rax
callq *0x20(%rax)
movl %eax, %ecx
movq 0xe8(%rsp), %rax
movl %ecx, 0x20c(%rsp)
movq 0x8(%rax), %rdi
movslq 0x214(%rsp), %rsi
callq 0xf9a0
movq %rax, %rdi
movslq 0x20c(%rsp), %rsi
callq 0xf9c0
movq (%rax), %rax
movq %rax, 0x200(%rsp)
movq 0x200(%rsp), %rax
testb $0x1, (%rax)
jne 0xb668
movl 0x20c(%rsp), %eax
movl %eax, 0x224(%rsp)
jmp 0xbff7
movq 0xe8(%rsp), %rdi
movq 0x200(%rsp), %rsi
callq 0xc020
movl %eax, 0x1fc(%rsp)
leaq 0x88965(%rip), %rax     # 0x93ff0
testb $0x1, 0x1cc(%rax)
je 0xbac9
movb $0x0, 0x1fb(%rsp)
cmpl $0x0, 0x1fc(%rsp)
jne 0xb6b4
testb $0x1, 0x213(%rsp)
jne 0xb6c8
cmpl $0x1, 0x1fc(%rsp)
jne 0xb6d0
testb $0x1, 0x213(%rsp)
jne 0xb6d0
movb $0x1, 0x1fb(%rsp)
movq 0xe8(%rsp), %rdi
addq $0x288, %rdi            # imm = 0x288
xorl %eax, %eax
movl %eax, %esi
callq 0xf860
movq %rax, %rsi
leaq 0x1c8(%rsp), %rdi
movq %rdi, 0xd8(%rsp)
callq 0xf880
movq 0xd8(%rsp), %rdi
movq 0x200(%rsp), %rax
movq 0x8(%rax), %rsi
movq 0x20(%rax), %rdx
callq 0x2ff40
movl %eax, 0xe4(%rsp)
jmp 0xb726
leaq 0x1c8(%rsp), %rdi
callq 0xf7b0
movl 0xe4(%rsp), %eax
movq 0xe8(%rsp), %rdi
movl %eax, 0x1f4(%rsp)
addq $0x270, %rdi            # imm = 0x270
callq 0xf840
movb $0x0, 0x18f(%rsp)
cmpq $0x1, %rax
jbe 0xb7d2
movq 0xe8(%rsp), %rdi
addq $0x288, %rdi            # imm = 0x288
movl $0x1, %esi
callq 0xf860
movq %rax, %rsi
leaq 0x190(%rsp), %rdi
movq %rdi, 0xc8(%rsp)
callq 0xf880
movq 0xc8(%rsp), %rdi
movb $0x1, 0x18f(%rsp)
movq 0x200(%rsp), %rax
movq 0x8(%rax), %rsi
movq 0x20(%rax), %rdx
callq 0x2ff40
movl %eax, 0xd4(%rsp)
jmp 0xb7c2
movl 0xd4(%rsp), %eax
movl %eax, 0xc4(%rsp)
jmp 0xb7dd
xorl %eax, %eax
movl %eax, 0xc4(%rsp)
jmp 0xb7dd
movl 0xc4(%rsp), %eax
movl %eax, 0xc0(%rsp)
testb $0x1, 0x18f(%rsp)
jne 0xb7f7
jmp 0xb804
leaq 0x190(%rsp), %rdi
callq 0xf7b0
movl 0xc0(%rsp), %eax
movl %eax, 0x1b8(%rsp)
testb $0x1, 0x1fb(%rsp)
je 0xb8b0
movq 0xe8(%rsp), %rdi
addq $0x490, %rdi            # imm = 0x490
movslq 0x1f4(%rsp), %rsi
callq 0xf9e0
movq %rax, %rdi
movslq 0x1b8(%rsp), %rsi
callq 0xfa00
movl (%rax), %ecx
addl $0x1, %ecx
movl %ecx, (%rax)
jmp 0xb8e5
movq %rax, %rcx
movl %edx, %eax
movq %rcx, 0x1c0(%rsp)
movl %eax, 0x1bc(%rsp)
leaq 0x1c8(%rsp), %rdi
callq 0xf7b0
jmp 0xc006
movq %rax, %rcx
movl %edx, %eax
movq %rcx, 0x1c0(%rsp)
movl %eax, 0x1bc(%rsp)
testb $0x1, 0x18f(%rsp)
jne 0xb89e
jmp 0xb8ab
leaq 0x190(%rsp), %rdi
callq 0xf7b0
jmp 0xc006
movq 0xe8(%rsp), %rdi
addq $0x490, %rdi            # imm = 0x490
movslq 0x1f4(%rsp), %rsi
callq 0xf9e0
movq %rax, %rdi
movslq 0x1b8(%rsp), %rsi
callq 0xfa00
movl 0x4(%rax), %ecx
addl $0x1, %ecx
movl %ecx, 0x4(%rax)
movl $0x0, 0x188(%rsp)
movq 0xe8(%rsp), %rdi
movl 0x188(%rsp), %eax
movq %rax, 0xb8(%rsp)
addq $0x270, %rdi            # imm = 0x270
callq 0xf840
movq %rax, %rcx
movq 0xb8(%rsp), %rax
cmpq %rcx, %rax
jae 0xbac7
movq 0xe8(%rsp), %rdi
addq $0x288, %rdi            # imm = 0x288
movl 0x188(%rsp), %eax
movl %eax, %esi
callq 0xf860
movq %rax, %rsi
leaq 0x158(%rsp), %rdi
movq %rdi, 0xa8(%rsp)
callq 0xf880
movq 0xa8(%rsp), %rdi
movq 0x200(%rsp), %rax
movq 0x8(%rax), %rsi
movq 0x20(%rax), %rdx
callq 0x2ff40
movl %eax, 0xb4(%rsp)
jmp 0xb982
leaq 0x158(%rsp), %rdi
callq 0xf7b0
movl 0xb4(%rsp), %eax
movl %eax, 0x184(%rsp)
movb $0x0, 0x157(%rsp)
cmpl $0x1, 0x1fc(%rsp)
jne 0xba02
movq 0x200(%rsp), %rdi
addq $0xd0, %rdi
movl 0x188(%rsp), %eax
movl %eax, %esi
callq 0xf900
cmpl $0x0, 0x4(%rax)
jne 0xba02
movb $0x1, 0x157(%rsp)
jmp 0xba39
movq %rax, %rcx
movl %edx, %eax
movq %rcx, 0x1c0(%rsp)
movl %eax, 0x1bc(%rsp)
leaq 0x158(%rsp), %rdi
callq 0xf7b0
jmp 0xc006
cmpl $0x0, 0x1fc(%rsp)
jne 0xba37
movq 0x200(%rsp), %rdi
addq $0xd0, %rdi
movl 0x188(%rsp), %eax
movl %eax, %esi
callq 0xf900
cmpl $0x1, 0x4(%rax)
jne 0xba37
movb $0x1, 0x157(%rsp)
jmp 0xba39
testb $0x1, 0x157(%rsp)
je 0xba79
movq 0xe8(%rsp), %rdi
addq $0x478, %rdi            # imm = 0x478
movl 0x188(%rsp), %eax
movl %eax, %esi
callq 0xf9e0
movq %rax, %rdi
movslq 0x184(%rsp), %rsi
callq 0xfa00
movl (%rax), %ecx
addl $0x1, %ecx
movl %ecx, (%rax)
jmp 0xbaaf
movq 0xe8(%rsp), %rdi
addq $0x478, %rdi            # imm = 0x478
movl 0x188(%rsp), %eax
movl %eax, %esi
callq 0xf9e0
movq %rax, %rdi
movslq 0x184(%rsp), %rsi
callq 0xfa00
movl 0x4(%rax), %ecx
addl $0x1, %ecx
movl %ecx, 0x4(%rax)
jmp 0xbab1
movl 0x188(%rsp), %eax
addl $0x1, %eax
movl %eax, 0x188(%rsp)
jmp 0xb8f0
jmp 0xbac9
cmpl $0x1, 0x1fc(%rsp)
jne 0xbadd
testb $0x1, 0x213(%rsp)
je 0xbaf9
cmpl $0x0, 0x1fc(%rsp)
jne 0xbf09
testb $0x1, 0x213(%rsp)
je 0xbf09
leaq 0x884f0(%rip), %rax     # 0x93ff0
testb $0x1, (%rax)
je 0xbeed
movb 0x213(%rsp), %dl
leaq 0x65d0c(%rip), %rcx     # 0x71823
leaq 0x65d0e(%rip), %rax     # 0x7182c
testb $0x1, %dl
cmovneq %rcx, %rax
movq %rax, 0x98(%rsp)
leaq 0x12f(%rsp), %rdi
movq %rdi, 0xa0(%rsp)
callq 0x56a0
movq 0x98(%rsp), %rsi
movq 0xa0(%rsp), %rdx
leaq 0x130(%rsp), %rdi
callq 0x5530
jmp 0xbb61
leaq 0x12f(%rsp), %rdi
callq 0x53e0
leaq 0x88443(%rip), %rax     # 0x93fb8
movq (%rax), %rsi
leaq 0x87981(%rip), %rdi     # 0x93500
callq 0x50f0
movq %rax, 0x90(%rsp)
jmp 0xbb8e
movq 0x90(%rsp), %rdi
leaq 0x65681(%rip), %rsi     # 0x7121e
callq 0x5380
movq %rax, 0x88(%rsp)
jmp 0xbbac
movq 0x88(%rsp), %rdi
leaq 0x3c45(%rip), %rsi      # 0xf800
callq 0x5160
movq %rax, 0x80(%rsp)
jmp 0xbbca
movq 0x80(%rsp), %rdi
movq 0x200(%rsp), %rax
movq 0x8(%rax), %rsi
callq 0x50f0
movq %rax, 0x78(%rsp)
jmp 0xbbea
movq 0x78(%rsp), %rdi
leaq 0x3c2a(%rip), %rsi      # 0xf820
callq 0x5160
movq %rax, 0x70(%rsp)
jmp 0xbc02
movq 0x70(%rsp), %rdi
leaq 0x65621(%rip), %rsi     # 0x7122f
callq 0x5380
movq %rax, 0x68(%rsp)
jmp 0xbc1a
movq 0x68(%rsp), %rdi
leaq 0x130(%rsp), %rsi
callq 0x5330
movq %rax, 0x60(%rsp)
jmp 0xbc33
movq 0x60(%rsp), %rdi
leaq 0x65609(%rip), %rsi     # 0x71248
callq 0x5380
movq %rax, 0x58(%rsp)
jmp 0xbc4b
movq 0x58(%rsp), %rdi
movq 0x200(%rsp), %rax
movsd 0x130(%rax), %xmm0
callq 0x56f0
movq %rax, 0x50(%rsp)
jmp 0xbc6c
movq 0x50(%rsp), %rdi
movq 0x87340(%rip), %rsi     # 0x92fb8
callq 0x53d0
jmp 0xbc7f
movl $0x0, 0x128(%rsp)
movq 0xe8(%rsp), %rdi
movl 0x128(%rsp), %eax
movq %rax, 0x48(%rsp)
addq $0x270, %rdi            # imm = 0x270
callq 0xf840
movq %rax, %rcx
movq 0x48(%rsp), %rax
cmpq %rcx, %rax
jae 0xbecc
movq 0xe8(%rsp), %rdi
addq $0x288, %rdi            # imm = 0x288
movl 0x128(%rsp), %eax
movl %eax, %esi
callq 0xf860
movq %rax, %rsi
leaq 0xf8(%rsp), %rdi
callq 0xf880
jmp 0xbcea
movq 0x200(%rsp), %rax
movq 0x8(%rax), %rsi
movq 0x20(%rax), %rdx
leaq 0xf8(%rsp), %rdi
callq 0x2ff40
movl %eax, 0x44(%rsp)
jmp 0xbd0d
leaq 0xf8(%rsp), %rdi
callq 0xf7b0
movl 0x44(%rsp), %eax
movq 0xe8(%rsp), %rdi
movl %eax, 0x124(%rsp)
addq $0x270, %rdi            # imm = 0x270
movl 0x128(%rsp), %eax
movl %eax, %esi
callq 0xf8c0
movq (%rax), %rdi
movl 0x124(%rsp), %esi
xorl %edx, %edx
callq 0x2d520
movl %eax, 0x40(%rsp)
jmp 0xbd59
movq 0xe8(%rsp), %rdi
movl 0x40(%rsp), %eax
movl %eax, 0xf4(%rsp)
addq $0x270, %rdi            # imm = 0x270
movl 0x128(%rsp), %eax
movl %eax, %esi
callq 0xf8c0
movq (%rax), %rdi
movl 0x124(%rsp), %esi
xorl %edx, %edx
callq 0x2d360
movl %eax, 0x3c(%rsp)
jmp 0xbd98
movl 0x3c(%rsp), %eax
movl %eax, 0xf0(%rsp)
leaq 0x87756(%rip), %rdi     # 0x93500
leaq 0x6549f(%rip), %rsi     # 0x71250
callq 0x5380
movq %rax, 0x30(%rsp)
jmp 0xbdbd
movq 0x30(%rsp), %rdi
movl 0x128(%rsp), %esi
callq 0x5510
movq %rax, 0x28(%rsp)
jmp 0xbdd5
movq 0x28(%rsp), %rdi
leaq 0x66e82(%rip), %rsi     # 0x72c63
callq 0x5380
movq %rax, 0x20(%rsp)
jmp 0xbded
movq 0x20(%rsp), %rdi
movl 0xf0(%rsp), %eax
movl %eax, %ecx
leaq 0x8762e(%rip), %rax     # 0x93430
movq (%rax,%rcx,8), %rsi
callq 0x5380
movq %rax, 0x18(%rsp)
jmp 0xbe12
movq 0x18(%rsp), %rdi
leaq 0x66e45(%rip), %rsi     # 0x72c63
callq 0x5380
movq %rax, 0x10(%rsp)
jmp 0xbe2a
movq 0x10(%rsp), %rdi
movl 0xf4(%rsp), %esi
callq 0x5680
movq %rax, 0x8(%rsp)
jmp 0xbe42
movq 0x8(%rsp), %rdi
movq 0x8716a(%rip), %rsi     # 0x92fb8
callq 0x53d0
jmp 0xbe55
jmp 0xbe57
movl 0x128(%rsp), %eax
addl $0x1, %eax
movl %eax, 0x128(%rsp)
jmp 0xbc8a
movq %rax, %rcx
movl %edx, %eax
movq %rcx, 0x1c0(%rsp)
movl %eax, 0x1bc(%rsp)
leaq 0x12f(%rsp), %rdi
callq 0x53e0
jmp 0xc006
movq %rax, %rcx
movl %edx, %eax
movq %rcx, 0x1c0(%rsp)
movl %eax, 0x1bc(%rsp)
jmp 0xbedb
movq %rax, %rcx
movl %edx, %eax
movq %rcx, 0x1c0(%rsp)
movl %eax, 0x1bc(%rsp)
leaq 0xf8(%rsp), %rdi
callq 0xf7b0
jmp 0xbedb
leaq 0x130(%rsp), %rdi
callq 0x5768
jmp 0xbeed
leaq 0x130(%rsp), %rdi
callq 0x5768
jmp 0xc006
movq 0xe8(%rsp), %rax
movq 0x438(%rax), %rcx
addq $0x1, %rcx
movq %rcx, 0x438(%rax)
jmp 0xbf23
movq 0xe8(%rsp), %rax
movq 0x430(%rax), %rcx
addq $0x1, %rcx
movq %rcx, 0x430(%rax)
movq 0x200(%rsp), %rax
testb $0x1, 0x14a(%rax)
je 0xbf65
leaq 0x880b5(%rip), %rax     # 0x93ff0
testb $0x1, 0x225(%rax)
jne 0xbf65
movq 0xe8(%rsp), %rdi
movq 0x200(%rsp), %rsi
movb 0x213(%rsp), %al
andb $0x1, %al
movzbl %al, %edx
callq 0xac60
movq 0x200(%rsp), %rax
cmpl $0x0, 0x11c(%rax)
jne 0xbfc2
movq 0x200(%rsp), %rax
cmpl $0x0, 0x120(%rax)
jne 0xbfc2
movq 0xe8(%rsp), %rdi
movq %rdi, %rax
addq $0x3a0, %rax            # imm = 0x3A0
movq %rax, (%rsp)
addq $0x3a0, %rdi            # imm = 0x3A0
callq 0xfa40
movq (%rsp), %rdi
movq %rax, %rsi
subq $0x1, %rsi
callq 0xfa20
movq (%rax), %rcx
addq $0x1, %rcx
movq %rcx, (%rax)
movq 0xe8(%rsp), %rdi
movl 0x214(%rsp), %esi
movl 0x20c(%rsp), %edx
movb 0x213(%rsp), %al
andb $0x1, %al
movzbl %al, %ecx
callq 0xc0a0
movl 0x20c(%rsp), %eax
movl %eax, 0x224(%rsp)
movl 0x224(%rsp), %eax
addq $0x228, %rsp            # imm = 0x228
retq
movq 0x1c0(%rsp), %rdi
callq 0x5690
nopw %cs:(%rax,%rax)