// File: gvaumour[P]cache-simulator/src/SaturationPredictor.cc
// Function: SaturationCounter::updatePolicy(unsigned long, unsigned long, bool, Access, bool)
void SaturationCounter::updatePolicy(uint64_t set, uint64_t index, bool inNVM, Access element , bool isWBrequest = false)
{
	//DPRINTF("SaturationCounter::updatePolicy\n");
	
	if(inNVM){
		//Update NVM entry 
		CacheEntry* current = m_tableNVM[set][index];
		current->policyInfo = m_cpt;
		
		if(element.isWrite()){
			current->saturation_counter++;
			if(current->saturation_counter == simu_parameters.saturation_threshold)
			{
				//Trigger Migration
				//Select LRU candidate from SRAM cache
				//DPRINTF("SaturationCounter:: Migration Triggered from NVM\n");

				int id_assoc = evictPolicy(set, false);
				
				CacheEntry* replaced_entry = m_tableSRAM[set][id_assoc];
			
				current->saturation_counter = 0;
				replaced_entry->saturation_counter = 0;
			
				/** Migration incurs one read and one extra write */ 
				replaced_entry->nbWrite++;
				current->nbRead++;

				Predictor::migrationRecording();
				m_cache->triggerMigration(set, id_assoc , index , true);
				if(!m_isWarmup)
					stats_nbMigrationsFromNVM[inNVM]++;

				
			}
		}
		else{
			current->saturation_counter--;
			if(current->saturation_counter < 0)
				current->saturation_counter = 0;					
		}
			
	}
	else{// Update SRAM entry 
		CacheEntry* current = m_tableSRAM[set][index];
		current->policyInfo = m_cpt;
		
		if(element.isWrite())
		{
			current->saturation_counter--;
			if(current->saturation_counter < 0)
				current->saturation_counter = 0;
		}
		else{
			current->saturation_counter++;
			if(current->saturation_counter == simu_parameters.saturation_threshold)
			{
				//Trigger Migration
				//DPRINTF("SaturationCounter:: Migration Triggered from SRAM\n");
				int id_assoc = evictPolicy(set, true);//Select LRU candidate from NVM cache

				CacheEntry* replaced_entry = m_tableNVM[set][id_assoc];
				assert(replaced_entry != NULL);
							
				current->saturation_counter = 0;
				replaced_entry->saturation_counter = 0;
		
				Predictor::migrationRecording();
		
				/** Migration incurs one read and one extra write */ 
				replaced_entry->nbWrite++;
				current->nbRead++;

				m_cache->triggerMigration(set, index, id_assoc, false);
			
				if(!m_isWarmup)
					stats_nbMigrationsFromNVM[inNVM]++;

			}
		}
	}
		
	Predictor::updatePolicy(set, index, inNVM, element , isWBrequest);

	m_cpt++;
}

// Assembly:
subq $0xe8, %rsp
movb %r8b, %al
leaq 0xf0(%rsp), %r8
movq %r8, 0x50(%rsp)
movq %rdi, 0xe0(%rsp)
movq %rsi, 0xd8(%rsp)
movq %rdx, 0xd0(%rsp)
andb $0x1, %cl
movb %cl, 0xcf(%rsp)
andb $0x1, %al
movb %al, 0xce(%rsp)
movq 0xe0(%rsp), %rax
movq %rax, 0x58(%rsp)
testb $0x1, 0xcf(%rsp)
je 0x5d8c7
movq 0x58(%rsp), %rax
movq 0x10(%rax), %rdi
movq 0xd8(%rsp), %rsi
callq 0xf9a0
movq %rax, %rdi
movq 0xd0(%rsp), %rsi
callq 0xf9c0
movq 0x50(%rsp), %rdi
movq %rax, %rcx
movq 0x58(%rsp), %rax
movq (%rcx), %rcx
movq %rcx, 0xc0(%rsp)
movl 0x270(%rax), %ecx
movq 0xc0(%rsp), %rax
movl %ecx, 0x38(%rax)
callq 0xf7c0
testb $0x1, %al
jne 0x5d73a
jmp 0x5d886
movq 0xc0(%rsp), %rax
movl 0x128(%rax), %ecx
addl $0x1, %ecx
movl %ecx, 0x128(%rax)
movq 0xc0(%rsp), %rax
movl 0x128(%rax), %eax
leaq 0x3688a(%rip), %rcx     # 0x93ff0
cmpl 0xb8(%rcx), %eax
jne 0x5d884
movq 0x58(%rsp), %rdi
movq 0xd8(%rsp), %rax
movl %eax, %esi
movq (%rdi), %rax
xorl %edx, %edx
callq *0x28(%rax)
movl %eax, %ecx
movq 0x58(%rsp), %rax
movl %ecx, 0xbc(%rsp)
movq 0x8(%rax), %rdi
movq 0xd8(%rsp), %rsi
callq 0xf9a0
movq %rax, %rdi
movslq 0xbc(%rsp), %rsi
callq 0xf9c0
movq 0x58(%rsp), %rdi
movq (%rax), %rax
movq %rax, 0xb0(%rsp)
movq 0xc0(%rsp), %rax
movl $0x0, 0x128(%rax)
movq 0xb0(%rsp), %rax
movl $0x0, 0x128(%rax)
movq 0xb0(%rsp), %rax
movl 0x11c(%rax), %ecx
addl $0x1, %ecx
movl %ecx, 0x11c(%rax)
movq 0xc0(%rsp), %rax
movl 0x120(%rax), %ecx
addl $0x1, %ecx
movl %ecx, 0x120(%rax)
callq 0x56e70
movq 0x58(%rsp), %rax
movq 0x70(%rax), %rdi
movq 0xd8(%rsp), %rax
movl %eax, %esi
movl 0xbc(%rsp), %edx
movq 0xd0(%rsp), %rax
movl %eax, %ecx
movl $0x1, %r8d
callq 0x3ac00
movq 0x58(%rsp), %rax
testb $0x1, 0x81(%rax)
jne 0x5d882
movq 0x58(%rsp), %rdi
addq $0x278, %rdi            # imm = 0x278
movb 0xcf(%rsp), %al
andb $0x1, %al
movzbl %al, %eax
movl %eax, %esi
callq 0xef90
movl (%rax), %ecx
addl $0x1, %ecx
movl %ecx, (%rax)
jmp 0x5d884
jmp 0x5d8c2
movq 0xc0(%rsp), %rax
movl 0x128(%rax), %ecx
addl $-0x1, %ecx
movl %ecx, 0x128(%rax)
movq 0xc0(%rsp), %rax
cmpl $0x0, 0x128(%rax)
jge 0x5d8c0
movq 0xc0(%rsp), %rax
movl $0x0, 0x128(%rax)
jmp 0x5d8c2
jmp 0x5dada
movq 0x58(%rsp), %rax
movq 0x8(%rax), %rdi
movq 0xd8(%rsp), %rsi
callq 0xf9a0
movq %rax, %rdi
movq 0xd0(%rsp), %rsi
callq 0xf9c0
movq 0x50(%rsp), %rdi
movq %rax, %rcx
movq 0x58(%rsp), %rax
movq (%rcx), %rcx
movq %rcx, 0xa8(%rsp)
movl 0x270(%rax), %ecx
movq 0xa8(%rsp), %rax
movl %ecx, 0x38(%rax)
callq 0xf7c0
testb $0x1, %al
jne 0x5d921
jmp 0x5d960
movq 0xa8(%rsp), %rax
movl 0x128(%rax), %ecx
addl $-0x1, %ecx
movl %ecx, 0x128(%rax)
movq 0xa8(%rsp), %rax
cmpl $0x0, 0x128(%rax)
jge 0x5d95b
movq 0xa8(%rsp), %rax
movl $0x0, 0x128(%rax)
jmp 0x5dad8
movq 0xa8(%rsp), %rax
movl 0x128(%rax), %ecx
addl $0x1, %ecx
movl %ecx, 0x128(%rax)
movq 0xa8(%rsp), %rax
movl 0x128(%rax), %eax
leaq 0x36664(%rip), %rcx     # 0x93ff0
cmpl 0xb8(%rcx), %eax
jne 0x5dad6
movq 0x58(%rsp), %rdi
movq 0xd8(%rsp), %rax
movl %eax, %esi
movq (%rdi), %rax
movl $0x1, %edx
callq *0x28(%rax)
movl %eax, %ecx
movq 0x58(%rsp), %rax
movl %ecx, 0xa4(%rsp)
movq 0x10(%rax), %rdi
movq 0xd8(%rsp), %rsi
callq 0xf9a0
movq %rax, %rdi
movslq 0xa4(%rsp), %rsi
callq 0xf9c0
movq (%rax), %rax
movq %rax, 0x98(%rsp)
cmpq $0x0, 0x98(%rsp)
je 0x5d9f9
jmp 0x5da18
leaq 0x16155(%rip), %rdi     # 0x73b55
leaq 0x16165(%rip), %rsi     # 0x73b6c
movl $0x5e, %edx
leaq 0x16174(%rip), %rcx     # 0x73b87
callq 0x5260
movq 0x58(%rsp), %rdi
movq 0xa8(%rsp), %rax
movl $0x0, 0x128(%rax)
movq 0x98(%rsp), %rax
movl $0x0, 0x128(%rax)
callq 0x56e70
movq 0x58(%rsp), %rax
movq 0x98(%rsp), %rcx
movl 0x11c(%rcx), %edx
addl $0x1, %edx
movl %edx, 0x11c(%rcx)
movq 0xa8(%rsp), %rcx
movl 0x120(%rcx), %edx
addl $0x1, %edx
movl %edx, 0x120(%rcx)
movq 0x70(%rax), %rdi
movq 0xd8(%rsp), %rax
movl %eax, %esi
movq 0xd0(%rsp), %rax
movl %eax, %edx
movl 0xa4(%rsp), %ecx
xorl %r8d, %r8d
callq 0x3ac00
movq 0x58(%rsp), %rax
testb $0x1, 0x81(%rax)
jne 0x5dad4
movq 0x58(%rsp), %rdi
addq $0x278, %rdi            # imm = 0x278
movb 0xcf(%rsp), %al
andb $0x1, %al
movzbl %al, %eax
movl %eax, %esi
callq 0xef90
movl (%rax), %ecx
addl $0x1, %ecx
movl %ecx, (%rax)
jmp 0x5dad6
jmp 0x5dad8
jmp 0x5dada
movq 0x50(%rsp), %rsi
movq 0xd8(%rsp), %rax
movq %rax, 0x40(%rsp)
movq 0xd0(%rsp), %rax
movq %rax, 0x48(%rsp)
movb 0xcf(%rsp), %al
movb %al, 0x3f(%rsp)
leaq 0x60(%rsp), %rdi
movl $0x38, %edx
callq 0x52f0
movb 0x3f(%rsp), %cl
movq 0x40(%rsp), %rsi
movq 0x48(%rsp), %rdx
movq 0x58(%rsp), %rdi
movb 0xce(%rsp), %al
movq 0x90(%rsp), %r9
movq %rsp, %r8
movq %r9, 0x30(%r8)
movups 0x60(%rsp), %xmm0
movups 0x70(%rsp), %xmm1
movups 0x80(%rsp), %xmm2
movups %xmm2, 0x20(%r8)
movups %xmm1, 0x10(%r8)
movups %xmm0, (%r8)
movzbl %cl, %ecx
andl $0x1, %ecx
movzbl %al, %r8d
andl $0x1, %r8d
callq 0x56ed0
movq 0x58(%rsp), %rax
movl 0x270(%rax), %ecx
addl $0x1, %ecx
movl %ecx, 0x270(%rax)
addq $0xe8, %rsp
retq
nopl (%rax,%rax)