// File: gvaumour[P]cache-simulator/src/PHC.cc
// Function: PHCPredictor::insertionPolicy(unsigned long, unsigned long, bool, Access)
void
PHCPredictor::insertionPolicy(uint64_t set, uint64_t index, bool inNVM, Access element)
{
	CacheEntry* entry = get_entry(set , index , inNVM);
	entry->policyInfo = m_cpt++;

	RD_TYPE rd = RD_NOT_ACCURATE;
	
	stats_allocate++;
	if( element.isSRAMerror)
	{
		rd = RD_MEDIUM;	
		stats_cptSRAMerror++;
	}
		
	stats_access_class[rd][element.isWrite()]++;
	
	/** Training learning cache lines */ 
	/*if(entry->isLearning)
	{
//		cout << "Insertion Learning Cache line 0x" << std::hex << element.block_addr << endl;
	*/
/*
	string alloc = inNVM ? "NVM" : "SRAM";
	cout << "Insertion Block addr = 0x" << std::hex << element.block_addr << std::dec << " in " << alloc << "; Prediction per feature:" << endl;
*/
	for(unsigned i = 0 ; i < m_features.size() ; i++)
	{
		int hash = m_features_hash[i](element.block_addr , element.m_pc);
		int pred = m_features[i]->getAllocationPrediction(hash, true);		
		allocDecision des = ALLOCATE_IN_SRAM;
		if( abs(pred) < simu_parameters.perceptron_allocation_threshold)
			des = element.isWrite() ? ALLOCATE_IN_SRAM : ALLOCATE_IN_NVM;
		if(pred > 0 )
			des = ALLOCATE_IN_NVM;
			
//		cout << "\t- " << m_criterias_names[i] << " : " << str_allocDecision[des]  << ", " << hash  << ", " << pred << endl; 
		entry->PHC_allocation_pred[i].second = des; 
		entry->PHC_allocation_pred[i].first = hash; 
		
	}
	if( element.isSRAMerror)
	{
		for(unsigned i = 0 ; i < m_features.size() ; i++)
		{
			int hash = m_features_hash[i](element.block_addr , element.m_pc);
			m_features[i]->increaseAlloc(hash);			
		}
		entry->cost_value = missingTagCostValue(element.block_addr , set) +  m_costAccess[element.isWrite()][RD_MEDIUM];
		stats_cptLearningSRAMerror++;		
	}
	else
		entry->cost_value = m_costAccess[element.isWrite()][RD_SHORT];

			
	Predictor::insertionPolicy(set , index , inNVM , element);
}

// Assembly:
subq $0x118, %rsp            # imm = 0x118
movb %cl, %al
leaq 0x120(%rsp), %rcx
movq %rcx, 0x90(%rsp)
movq %rdi, 0x110(%rsp)
movq %rsi, 0x108(%rsp)
movq %rdx, 0x100(%rsp)
andb $0x1, %al
movb %al, 0xff(%rsp)
movq 0x110(%rsp), %rdi
movq %rdi, 0x88(%rsp)
movq 0x108(%rsp), %rsi
movq 0x100(%rsp), %rdx
movb 0xff(%rsp), %al
andb $0x1, %al
movzbl %al, %ecx
callq 0x4ae70
movq 0x88(%rsp), %rcx
movq %rax, %rdx
movq 0x90(%rsp), %rax
movq %rdx, 0xf0(%rsp)
movq 0x2d8(%rcx), %rdx
movq %rdx, %rsi
addq $0x1, %rsi
movq %rsi, 0x2d8(%rcx)
movl %edx, %esi
movq 0xf0(%rsp), %rdx
movl %esi, 0x38(%rdx)
movl $0x2, 0xec(%rsp)
movq 0x3b8(%rcx), %rdx
addq $0x1, %rdx
movq %rdx, 0x3b8(%rcx)
testb $0x1, 0x28(%rax)
je 0x4b210
movq 0x88(%rsp), %rax
movl $0x1, 0xec(%rsp)
movq 0x3d0(%rax), %rcx
addq $0x1, %rcx
movq %rcx, 0x3d0(%rax)
movq 0x88(%rsp), %rdi
addq $0x430, %rdi            # imm = 0x430
movl 0xec(%rsp), %eax
movl %eax, %esi
callq 0xef70
movq 0x90(%rsp), %rdi
movq %rax, 0x80(%rsp)
callq 0xf7c0
movq 0x80(%rsp), %rdi
andb $0x1, %al
movzbl %al, %eax
movl %eax, %esi
callq 0xef90
movl (%rax), %ecx
addl $0x1, %ecx
movl %ecx, (%rax)
movl $0x0, 0xe8(%rsp)
movq 0x88(%rsp), %rdi
movl 0xe8(%rsp), %eax
movq %rax, 0x78(%rsp)
addq $0x270, %rdi            # imm = 0x270
callq 0xf840
movq %rax, %rcx
movq 0x78(%rsp), %rax
cmpq %rcx, %rax
jae 0x4b3dd
movq 0x88(%rsp), %rdi
addq $0x288, %rdi            # imm = 0x288
movl 0xe8(%rsp), %eax
movl %eax, %esi
callq 0x4d780
movq 0x90(%rsp), %rcx
movq (%rax), %rax
movq 0x30(%rcx), %rdi
movq 0x10(%rcx), %rsi
callq *%rax
movq 0x88(%rsp), %rdi
movl %eax, 0xe4(%rsp)
addq $0x270, %rdi            # imm = 0x270
movl 0xe8(%rsp), %eax
movl %eax, %esi
callq 0xf8c0
movq (%rax), %rdi
movl 0xe4(%rsp), %esi
movl $0x1, %edx
callq 0x2d4e0
movl %eax, 0xe0(%rsp)
movl $0x0, 0xdc(%rsp)
movl 0xe0(%rsp), %eax
movl %eax, %ecx
negl %ecx
cmovnsl %ecx, %eax
leaq 0x48cc6(%rip), %rcx     # 0x93ff0
cmpl 0x1c0(%rcx), %eax
jge 0x4b355
movq 0x90(%rsp), %rdi
callq 0xf7c0
movb %al, %dl
movl $0x1, %eax
xorl %ecx, %ecx
testb $0x1, %dl
cmovnel %ecx, %eax
movl %eax, 0xdc(%rsp)
cmpl $0x0, 0xe0(%rsp)
jle 0x4b36a
movl $0x1, 0xdc(%rsp)
movl 0xdc(%rsp), %eax
movl %eax, 0x70(%rsp)
movq 0xf0(%rsp), %rdi
addq $0xd0, %rdi
movl 0xe8(%rsp), %eax
movl %eax, %esi
callq 0xf900
movl 0x70(%rsp), %ecx
movl %ecx, 0x4(%rax)
movl 0xe4(%rsp), %eax
movl %eax, 0x74(%rsp)
movq 0xf0(%rsp), %rdi
addq $0xd0, %rdi
movl 0xe8(%rsp), %eax
movl %eax, %esi
callq 0xf900
movl 0x74(%rsp), %ecx
movl %ecx, (%rax)
movl 0xe8(%rsp), %eax
addl $0x1, %eax
movl %eax, 0xe8(%rsp)
jmp 0x4b268
movq 0x90(%rsp), %rax
testb $0x1, 0x28(%rax)
je 0x4b542
movl $0x0, 0xd8(%rsp)
movq 0x88(%rsp), %rdi
movl 0xd8(%rsp), %eax
movq %rax, 0x68(%rsp)
addq $0x270, %rdi            # imm = 0x270
callq 0xf840
movq %rax, %rcx
movq 0x68(%rsp), %rax
cmpq %rcx, %rax
jae 0x4b4a2
movq 0x88(%rsp), %rdi
addq $0x288, %rdi            # imm = 0x288
movl 0xd8(%rsp), %eax
movl %eax, %esi
callq 0x4d780
movq 0x90(%rsp), %rcx
movq (%rax), %rax
movq 0x30(%rcx), %rdi
movq 0x10(%rcx), %rsi
callq *%rax
movq 0x88(%rsp), %rdi
movl %eax, 0xd4(%rsp)
addq $0x270, %rdi            # imm = 0x270
movl 0xd8(%rsp), %eax
movl %eax, %esi
callq 0xf8c0
movq (%rax), %rdi
movl 0xd4(%rsp), %esi
callq 0x2d480
movl 0xd8(%rsp), %eax
addl $0x1, %eax
movl %eax, 0xd8(%rsp)
jmp 0x4b3fa
movq 0x88(%rsp), %rdi
movq 0x90(%rsp), %rax
movq 0x30(%rax), %rsi
movq 0x108(%rsp), %rax
movl %eax, %edx
callq 0x56400
movq 0x90(%rsp), %rdi
movl %eax, %ecx
movq 0x88(%rsp), %rax
movl %ecx, 0x64(%rsp)
addq $0x2b8, %rax            # imm = 0x2B8
movq %rax, 0x58(%rsp)
callq 0xf7c0
movq 0x58(%rsp), %rdi
andb $0x1, %al
movzbl %al, %eax
movl %eax, %esi
callq 0xef70
movq %rax, %rdi
movl $0x1, %esi
callq 0xef90
movl 0x64(%rsp), %ecx
movq %rax, %rdx
movq 0x88(%rsp), %rax
addl (%rdx), %ecx
cvtsi2sd %ecx, %xmm0
movq 0xf0(%rsp), %rcx
movsd %xmm0, 0x130(%rcx)
movq 0x3c8(%rax), %rcx
addq $0x1, %rcx
movq %rcx, 0x3c8(%rax)
jmp 0x4b593
movq 0x90(%rsp), %rdi
movq 0x88(%rsp), %rax
addq $0x2b8, %rax            # imm = 0x2B8
movq %rax, 0x50(%rsp)
callq 0xf7c0
movq 0x50(%rsp), %rdi
andb $0x1, %al
movzbl %al, %eax
movl %eax, %esi
callq 0xef70
movq %rax, %rdi
xorl %eax, %eax
movl %eax, %esi
callq 0xef90
cvtsi2sdl (%rax), %xmm0
movq 0xf0(%rsp), %rax
movsd %xmm0, 0x130(%rax)
movq 0x90(%rsp), %rsi
movq 0x108(%rsp), %rax
movq %rax, 0x40(%rsp)
movq 0x100(%rsp), %rax
movq %rax, 0x48(%rsp)
movb 0xff(%rsp), %al
movb %al, 0x3f(%rsp)
leaq 0x98(%rsp), %rdi
movl $0x38, %edx
callq 0x52f0
movb 0x3f(%rsp), %al
movq 0x88(%rsp), %rdi
movq 0x40(%rsp), %rsi
movq 0x48(%rsp), %rdx
movq 0xc8(%rsp), %r8
movq %rsp, %rcx
movq %r8, 0x30(%rcx)
movups 0x98(%rsp), %xmm0
movups 0xa8(%rsp), %xmm1
movups 0xb8(%rsp), %xmm2
movups %xmm2, 0x20(%rcx)
movups %xmm1, 0x10(%rcx)
movups %xmm0, (%rcx)
movzbl %al, %ecx
andl $0x1, %ecx
callq 0x55140
addq $0x118, %rsp            # imm = 0x118
retq
nopl (%rax)