// File: /workspace/github_cpp_makefile_star2_O3/gvaumour[P]cache-simulator/src/SimplePerceptron.cc
// Function: SimplePerceptronPredictor::checkLazyMigration(CacheEntry*, unsigned long, bool, unsigned long, bool)
CacheEntry*
SimplePerceptronPredictor::checkLazyMigration(CacheEntry* current ,uint64_t set,bool inNVM, uint64_t index, bool isWrite)
{

	int yout = 0;
	for(unsigned i = 0 ; i < m_features.size() ; i++)
	{
		int hash = hashing_function1( m_features_hash[i] , current->address , current->missPC );
		int pred = m_features[i]->getCounter(hash);
		yout += pred;
	}
	
	if ( abs(yout) < simu_parameters.simple_perceptron_learningTreshold)
		return current;

	allocDecision des = yout > 0 ? ALLOCATE_IN_NVM : ALLOCATE_IN_SRAM;

	if( inNVM == false && des == ALLOCATE_IN_NVM)
	{
		//cl is SRAM , check whether we should migrate to NVM 
		if(simu_parameters.enableDatasetSpilling && m_isNVMbusy[set])
		{
			//reportSpilling(rap_current, current->address, false ,  inNVM);
			//stats_busyness_migrate_change++; //If NVM tab is busy , don't migrate
		}
		else
		{
			//Trigger Migration
			int id_assocNVM = evictPolicy(set, true);//Select LRU candidate from NVM cache
			//DPRINTF("DBAMBPredictor:: Migration Triggered from SRAM, index %ld, id_assoc %d \n" , index, id_assoc);

			CacheEntry* replaced_entry_NVM = m_tableNVM[set][id_assocNVM];
					
			/** Migration incurs one read and one extra write */ 
			replaced_entry_NVM->nbWrite++;
			current->nbRead++;
		
			/* Record the write error migration */ 
			Predictor::migrationRecording();
		
			reportMigration(current, false , isWrite);
		
			m_cache->triggerMigration(set, index , id_assocNVM , false);
			if(!m_isWarmup)
				stats_nbMigrations[true]++;


			current = replaced_entry_NVM;
		}

	}
	else if( des == ALLOCATE_IN_SRAM && inNVM == true)
	{
		//cl is in NVM , check whether we should migrate to SRAM 
			
		//If SRAM tab is busy , don't migrate
		if(simu_parameters.enableDatasetSpilling && m_isSRAMbusy[set])
		{
			//reportSpilling(rap_current, current->address, false ,  inNVM);
			//stats_busyness_migrate_change++; //If NVM tab is busy , don't migrate
		}
		else 
		{		
			int id_assocSRAM = evictPolicy(set, false);
		
			CacheEntry* replaced_entry_SRAM = m_tableSRAM[set][id_assocSRAM];

			/** Migration incurs one read and one extra write */ 
			replaced_entry_SRAM->nbWrite++;
			current->nbRead++;
			reportMigration( current, true , isWrite);
	
			m_cache->triggerMigration(set, id_assocSRAM , index , true);
		
			if(!m_isWarmup)
				stats_nbMigrations[false]++;

			current = replaced_entry_SRAM;		
		}

	}
	return current;
}

// Assembly:
pushq %rbp
pushq %r15
pushq %r14
pushq %r13
pushq %r12
pushq %rbx
subq $0x48, %rsp
movq %r8, 0x18(%rsp)
movl %ecx, 0x10(%rsp)
movq %rdx, 0x8(%rsp)
movq %rsi, (%rsp)
movq %rdi, %rbx
movq 0x278(%rdi), %rax
cmpq 0x270(%rdi), %rax
je 0x2c5f4
xorl %ebp, %ebp
movl $0x1, %r12d
leaq 0x30(%rsp), %rax
xorl %esi, %esi
movl %esi, 0x14(%rsp)
movq %rbx, %r15
movq 0x288(%rbx), %r14
leaq (,%rbp,4), %r13
addq %rbp, %r13
movq %rax, 0x20(%rsp)
movq (%r14,%r13,8), %rsi
movq 0x8(%r14,%r13,8), %rdx
addq %rsi, %rdx
leaq 0x20(%rsp), %rdi
movq %rax, %rbx
callq 0xcbd6
movq 0x20(%r14,%r13,8), %rax
movq %rax, 0x40(%rsp)
movq (%rsp), %rax
movq 0x8(%rax), %rsi
movq 0x20(%rax), %rdx
leaq 0x20(%rsp), %rdi
callq 0x159f0
movl %eax, %r14d
movq 0x20(%rsp), %rdi
movq %rbx, %r13
cmpq %rbx, %rdi
je 0x2c5b2
callq 0x52b0
movq %r15, %rbx
movq 0x270(%r15), %rax
movq (%rax,%rbp,8), %rdi
movl %r14d, %esi
callq 0x2a034
movl 0x14(%rsp), %esi
addl %eax, %esi
movq 0x278(%r15), %rax
subq 0x270(%r15), %rax
movl %r12d, %ebp
sarq $0x3, %rax
incl %r12d
cmpq %rbp, %rax
movq %r13, %rax
ja 0x2c546
jmp 0x2c5f6
xorl %esi, %esi
movl %esi, %ecx
negl %ecx
cmovsl %esi, %ecx
leaq 0x1994c(%rip), %rax     # 0x45f50
cmpl 0x248(%rax), %ecx
jl 0x2c7d1
testl %esi, %esi
setle %cl
movl 0x10(%rsp), %edx
orb %dl, %cl
jne 0x2c6fb
cmpb $0x1, 0x158(%rax)
jne 0x2c672
movq 0x8(%rsp), %rdi
leaq 0x3f(%rdi), %rax
testq %rdi, %rdi
cmovnsq %rdi, %rax
sarq $0x6, %rax
shlq $0x3, %rax
addq 0x110(%rbx), %rax
movabsq $-0x8000000000000000, %rcx # imm = 0x8000000000000000
leaq 0x3f(%rcx), %rdx
andq %rdi, %rdx
xorl %esi, %esi
cmpq %rcx, %rdx
setbe %sil
movq -0x8(%rax,%rsi,8), %rax
btq %rdi, %rax
jb 0x2c7d1
movq (%rbx), %rax
movq %rbx, %rdi
movq 0x8(%rsp), %r12
movl %r12d, %esi
movl $0x1, %edx
callq *0x28(%rax)
movq 0x10(%rbx), %rcx
movq (%rcx), %rcx
leaq (%r12,%r12,2), %rdx
movslq %eax, %r14
movq (%rcx,%rdx,8), %rax
movq (%rax,%r14,8), %r15
incl 0x11c(%r15)
movq (%rsp), %r13
incl 0x120(%r13)
movq %rbx, %rdi
callq 0x272c6
movq %rbx, %rdi
movq %r13, %rsi
xorl %edx, %edx
xorl %ecx, %ecx
callq 0x2d27a
movq 0x70(%rbx), %rdi
movl %r12d, %esi
movq 0x18(%rsp), %rdx
movl %r14d, %ecx
xorl %r8d, %r8d
callq 0x1b612
cmpb $0x0, 0x81(%rbx)
jne 0x2c7cd
movq 0x350(%rbx), %rax
addq $0x4, %rax
jmp 0x2c7cb
xorb $0x1, %dl
testl %esi, %esi
setg %cl
orb %dl, %cl
jne 0x2c7d1
cmpb $0x1, 0x158(%rax)
jne 0x2c758
movq 0x8(%rsp), %rdi
leaq 0x3f(%rdi), %rax
testq %rdi, %rdi
cmovnsq %rdi, %rax
sarq $0x6, %rax
shlq $0x3, %rax
addq 0xe8(%rbx), %rax
movabsq $-0x8000000000000000, %rcx # imm = 0x8000000000000000
leaq 0x3f(%rcx), %rdx
andq %rdi, %rdx
xorl %esi, %esi
cmpq %rcx, %rdx
setbe %sil
movq -0x8(%rax,%rsi,8), %rax
btq %rdi, %rax
jb 0x2c7d1
movq (%rbx), %rax
movq %rbx, %rdi
movq 0x8(%rsp), %r12
movl %r12d, %esi
xorl %edx, %edx
callq *0x28(%rax)
movq 0x8(%rbx), %rcx
movq (%rcx), %rcx
leaq (%r12,%r12,2), %rdx
movslq %eax, %r14
movq (%rcx,%rdx,8), %rax
movq (%rax,%r14,8), %r15
incl 0x11c(%r15)
movq (%rsp), %rsi
incl 0x120(%rsi)
movq %rbx, %rdi
movl $0x1, %edx
xorl %ecx, %ecx
callq 0x2d27a
movq 0x70(%rbx), %rdi
movl %r12d, %esi
movl %r14d, %edx
movq 0x18(%rsp), %rcx
movl $0x1, %r8d
callq 0x1b612
cmpb $0x0, 0x81(%rbx)
jne 0x2c7cd
movq 0x350(%rbx), %rax
incl (%rax)
movq %r15, (%rsp)
movq (%rsp), %rax
addq $0x48, %rsp
popq %rbx
popq %r12
popq %r13
popq %r14
popq %r15
popq %rbp
retq
movq %rax, %r14
movq 0x20(%rsp), %rdi
cmpq %rbx, %rdi
je 0x2c7f6
callq 0x52b0
movq %r14, %rdi
callq 0x55a0