// File: estwings57[P]CasHMC/sources/CasHMCWrapper.cpp
// Function: CasHMC::CasHMCWrapper::Update()
void CasHMCWrapper::Update()
{
	if(BANDWIDTH_PLOT && currentClockCycle > 0 && currentClockCycle%PLOT_SAMPLING == 0) {
		MakePlotData();
	}
	
#ifdef DEBUG_LOG
	if(currentClockCycle > 0 && currentClockCycle%LOG_EPOCH == 0) {
		cout<<"\n   === Simulation ["<<currentClockCycle/LOG_EPOCH<<"] epoch starts  ( CPU clk:"<<currentClockCycle<<" ) ===   "<<endl;
		PrintEpochStatistic();
		if(DEBUG_SIM) {
			debugOut.flush();	debugOut.close();
		}
		if(STATE_SIM) {
			stateOut.flush();	stateOut.close();
		}
		if(DEBUG_SIM || STATE_SIM) {
			PrintEpochHeader();
		}
	}
#endif

	//
	//update all class (HMC controller, links, and HMC block)
	//Roughly synchronize CPU clock cycle, link speed, and HMC clock cycle
	//
	hmcCont->Update();
	//Link master and slave are separately updated to flow packet from master to slave regardless of downstream or upstream
	for(int l=0; l<NUM_LINKS; l++) {
		hmcCont->downLinkMasters[l]->Update();
	}
	
		//Downstream links update at CPU clock cycle (depending on ratio of CPU cycle to Link cycle)
		while(CPU_CLK_PERIOD*downLinkTuner > linkPeriod*(downLinkClock + 1)) {
			DownLinkUpdate(false);
		}
		if(CPU_CLK_PERIOD*downLinkTuner == linkPeriod*(downLinkClock + 1)) {
			DownLinkUpdate(false);
			downLinkTuner = 0;
			downLinkClock = 0;
		}
		DownLinkUpdate(true);
	
			//HMC update at CPU clock cycle
			if(CPU_CLK_PERIOD <= tCK) {
				if(CPU_CLK_PERIOD*dramTuner > tCK*hmc->clockTuner) {
					hmc->Update();
				}
				else if(CPU_CLK_PERIOD*dramTuner == tCK*hmc->clockTuner) {
					dramTuner = 0;
					hmc->clockTuner = 0;
					hmc->Update();
				}
			}
			else {
				while(CPU_CLK_PERIOD*dramTuner > tCK*(hmc->clockTuner + 1)) {
					hmc->Update();
				}
				if(CPU_CLK_PERIOD*dramTuner == tCK*(hmc->clockTuner + 1)) {
					hmc->Update();
					dramTuner = 0;
					hmc->clockTuner = 0;
				}
				hmc->Update();
			}
		
		//Upstream links update at CPU clock cycle (depending on ratio of CPU cycle to Link cycle)
		while(CPU_CLK_PERIOD*upLinkTuner > linkPeriod*(upLinkClock + 1)) {
			UpLinkUpdate(false);
		}
		if(CPU_CLK_PERIOD*upLinkTuner == linkPeriod*(upLinkClock + 1)) {
			UpLinkUpdate(false);
			upLinkTuner = 0;
			upLinkClock = 0;
		}
		UpLinkUpdate(true);
	
	//Link master and slave are separately updated to flow packet from master to slave regardless of downstream or upstream
	for(int l=0; l<NUM_LINKS; l++) {
		hmcCont->upLinkSlaves[l]->Update();
	}
	
#ifndef DEBUG_LOG
	cout<<endl;
#endif
	//Print respective class state
	hmcCont->PrintState();
	for(int l=0; l<NUM_LINKS; l++) {
		hmcCont->downLinkMasters[l]->PrintState();
	}
		for(int l=0; l<NUM_LINKS; l++) {
			downstreamLinks[l]->PrintState();
		}
			hmc->PrintState();
		for(int l=0; l<NUM_LINKS; l++) {
			upstreamLinks[l]->PrintState();
		}
	for(int l=0; l<NUM_LINKS; l++) {
		hmcCont->upLinkSlaves[l]->PrintState();
	}
	
	currentClockCycle++;
	downLinkTuner++;
	upLinkTuner++;
	dramTuner++;
	DE_ST("\n---------------------------------------[ CPU clk:"<<currentClockCycle<<" / HMC clk:"<<hmc->currentClockCycle<<" ]---------------------------------------");
}

// Assembly:
pushq %rbp
movq %rsp, %rbp
subq $0x30, %rsp
movq %rdi, -0x8(%rbp)
movq -0x8(%rbp), %rax
movq %rax, -0x28(%rbp)
leaq 0x51875(%rip), %rax     # 0x66530
testb $0x1, (%rax)
je 0x14cf7
movq -0x28(%rbp), %rax
cmpq $0x0, 0x370(%rax)
jbe 0x14cf7
movq -0x28(%rbp), %rax
movq 0x370(%rax), %rax
leaq 0x5184c(%rip), %rcx     # 0x6652c
movslq (%rcx), %rcx
xorl %edx, %edx
divq %rcx
cmpq $0x0, %rdx
jne 0x14cf7
movq -0x28(%rbp), %rdi
callq 0x15490
movq -0x28(%rbp), %rax
movq 0x330(%rax), %rdi
movq (%rdi), %rax
callq *0x10(%rax)
movl $0x0, -0xc(%rbp)
movl -0xc(%rbp), %eax
leaq 0x5182f(%rip), %rcx     # 0x66548
cmpl (%rcx), %eax
jge 0x14d4c
movq -0x28(%rbp), %rax
movq 0x330(%rax), %rdi
addq $0x208, %rdi            # imm = 0x208
movslq -0xc(%rbp), %rsi
callq 0x17770
movq (%rax), %rdi
movq (%rdi), %rax
callq *0x10(%rax)
movl -0xc(%rbp), %eax
addl $0x1, %eax
movl %eax, -0xc(%rbp)
jmp 0x14d0f
jmp 0x14d4e
movq -0x28(%rbp), %rax
leaq 0x517df(%rip), %rcx     # 0x66538
movsd (%rcx), %xmm0
movq 0x380(%rax), %xmm1
movaps 0x3c3b4(%rip), %xmm4    # 0x51120
punpckldq %xmm4, %xmm1    # xmm1 = xmm1[0],xmm4[0],xmm1[1],xmm4[1]
movapd 0x3c3b8(%rip), %xmm3    # 0x51130
subpd %xmm3, %xmm1
movaps %xmm1, %xmm2
unpckhpd %xmm1, %xmm1            # xmm1 = xmm1[1,1]
addsd %xmm2, %xmm1
mulsd %xmm1, %xmm0
movsd 0x3a0(%rax), %xmm1
movq 0x388(%rax), %rax
incq %rax
movq %rax, %xmm2
punpckldq %xmm4, %xmm2    # xmm2 = xmm2[0],xmm4[0],xmm2[1],xmm4[1]
subpd %xmm3, %xmm2
movaps %xmm2, %xmm3
unpckhpd %xmm2, %xmm2            # xmm2 = xmm2[1,1]
addsd %xmm3, %xmm2
mulsd %xmm2, %xmm1
ucomisd %xmm1, %xmm0
jbe 0x14dcc
movq -0x28(%rbp), %rdi
xorl %esi, %esi
callq 0x15bc0
jmp 0x14d4e
movq -0x28(%rbp), %rax
leaq 0x51761(%rip), %rcx     # 0x66538
movsd (%rcx), %xmm0
movq 0x380(%rax), %xmm1
movaps 0x3c336(%rip), %xmm4    # 0x51120
punpckldq %xmm4, %xmm1    # xmm1 = xmm1[0],xmm4[0],xmm1[1],xmm4[1]
movapd 0x3c33a(%rip), %xmm3    # 0x51130
subpd %xmm3, %xmm1
movaps %xmm1, %xmm2
unpckhpd %xmm1, %xmm1            # xmm1 = xmm1[1,1]
addsd %xmm2, %xmm1
mulsd %xmm1, %xmm0
movsd 0x3a0(%rax), %xmm1
movq 0x388(%rax), %rax
incq %rax
movq %rax, %xmm2
punpckldq %xmm4, %xmm2    # xmm2 = xmm2[0],xmm4[0],xmm2[1],xmm4[1]
subpd %xmm3, %xmm2
movaps %xmm2, %xmm3
unpckhpd %xmm2, %xmm2            # xmm2 = xmm2[1,1]
addsd %xmm3, %xmm2
mulsd %xmm2, %xmm1
ucomisd %xmm1, %xmm0
jne 0x14e64
jp 0x14e64
movq -0x28(%rbp), %rdi
xorl %esi, %esi
callq 0x15bc0
movq -0x28(%rbp), %rax
movq $0x0, 0x380(%rax)
movq $0x0, 0x388(%rax)
movq -0x28(%rbp), %rdi
movl $0x1, %esi
callq 0x15bc0
leaq 0x516bf(%rip), %rax     # 0x66538
movsd (%rax), %xmm1
leaq 0x517bc(%rip), %rax     # 0x66640
movsd (%rax), %xmm0
ucomisd %xmm1, %xmm0
jb 0x14fc7
movq -0x28(%rbp), %rax
leaq 0x5169b(%rip), %rcx     # 0x66538
movsd (%rcx), %xmm0
movq 0x378(%rax), %xmm1
movaps 0x3c270(%rip), %xmm4    # 0x51120
punpckldq %xmm4, %xmm1    # xmm1 = xmm1[0],xmm4[0],xmm1[1],xmm4[1]
movapd 0x3c274(%rip), %xmm3    # 0x51130
subpd %xmm3, %xmm1
movaps %xmm1, %xmm2
unpckhpd %xmm1, %xmm1            # xmm1 = xmm1[1,1]
addsd %xmm2, %xmm1
mulsd %xmm1, %xmm0
leaq 0x5176a(%rip), %rcx     # 0x66640
movsd (%rcx), %xmm1
movq 0x368(%rax), %rax
movq 0x1c8(%rax), %xmm2
punpckldq %xmm4, %xmm2    # xmm2 = xmm2[0],xmm4[0],xmm2[1],xmm4[1]
subpd %xmm3, %xmm2
movaps %xmm2, %xmm3
unpckhpd %xmm2, %xmm2            # xmm2 = xmm2[1,1]
addsd %xmm3, %xmm2
mulsd %xmm2, %xmm1
ucomisd %xmm1, %xmm0
jbe 0x14f1c
movq -0x28(%rbp), %rax
movq 0x368(%rax), %rdi
movq (%rdi), %rax
callq *0x10(%rax)
jmp 0x14fc2
movq -0x28(%rbp), %rax
leaq 0x51611(%rip), %rcx     # 0x66538
movsd (%rcx), %xmm0
movq 0x378(%rax), %xmm1
movaps 0x3c1e6(%rip), %xmm4    # 0x51120
punpckldq %xmm4, %xmm1    # xmm1 = xmm1[0],xmm4[0],xmm1[1],xmm4[1]
movapd 0x3c1ea(%rip), %xmm3    # 0x51130
subpd %xmm3, %xmm1
movaps %xmm1, %xmm2
unpckhpd %xmm1, %xmm1            # xmm1 = xmm1[1,1]
addsd %xmm2, %xmm1
mulsd %xmm1, %xmm0
leaq 0x516e0(%rip), %rcx     # 0x66640
movsd (%rcx), %xmm1
movq 0x368(%rax), %rax
movq 0x1c8(%rax), %xmm2
punpckldq %xmm4, %xmm2    # xmm2 = xmm2[0],xmm4[0],xmm2[1],xmm4[1]
subpd %xmm3, %xmm2
movaps %xmm2, %xmm3
unpckhpd %xmm2, %xmm2            # xmm2 = xmm2[1,1]
addsd %xmm3, %xmm2
mulsd %xmm2, %xmm1
ucomisd %xmm1, %xmm0
jne 0x14fc0
jp 0x14fc0
movq -0x28(%rbp), %rax
movq $0x0, 0x378(%rax)
movq 0x368(%rax), %rcx
movq $0x0, 0x1c8(%rcx)
movq 0x368(%rax), %rdi
movq (%rdi), %rax
callq *0x10(%rax)
jmp 0x14fc2
jmp 0x1511a
jmp 0x14fc9
movq -0x28(%rbp), %rax
leaq 0x51564(%rip), %rcx     # 0x66538
movsd (%rcx), %xmm0
movq 0x378(%rax), %xmm1
movaps 0x3c139(%rip), %xmm4    # 0x51120
punpckldq %xmm4, %xmm1    # xmm1 = xmm1[0],xmm4[0],xmm1[1],xmm4[1]
movapd 0x3c13d(%rip), %xmm3    # 0x51130
subpd %xmm3, %xmm1
movaps %xmm1, %xmm2
unpckhpd %xmm1, %xmm1            # xmm1 = xmm1[1,1]
addsd %xmm2, %xmm1
mulsd %xmm1, %xmm0
leaq 0x51633(%rip), %rcx     # 0x66640
movsd (%rcx), %xmm1
movq 0x368(%rax), %rax
movq 0x1c8(%rax), %rax
incq %rax
movq %rax, %xmm2
punpckldq %xmm4, %xmm2    # xmm2 = xmm2[0],xmm4[0],xmm2[1],xmm4[1]
subpd %xmm3, %xmm2
movaps %xmm2, %xmm3
unpckhpd %xmm2, %xmm2            # xmm2 = xmm2[1,1]
addsd %xmm3, %xmm2
mulsd %xmm2, %xmm1
ucomisd %xmm1, %xmm0
jbe 0x1505a
movq -0x28(%rbp), %rax
movq 0x368(%rax), %rdi
movq (%rdi), %rax
callq *0x10(%rax)
jmp 0x14fc9
movq -0x28(%rbp), %rax
leaq 0x514d3(%rip), %rcx     # 0x66538
movsd (%rcx), %xmm0
movq 0x378(%rax), %xmm1
movaps 0x3c0a8(%rip), %xmm4    # 0x51120
punpckldq %xmm4, %xmm1    # xmm1 = xmm1[0],xmm4[0],xmm1[1],xmm4[1]
movapd 0x3c0ac(%rip), %xmm3    # 0x51130
subpd %xmm3, %xmm1
movaps %xmm1, %xmm2
unpckhpd %xmm1, %xmm1            # xmm1 = xmm1[1,1]
addsd %xmm2, %xmm1
mulsd %xmm1, %xmm0
leaq 0x515a2(%rip), %rcx     # 0x66640
movsd (%rcx), %xmm1
movq 0x368(%rax), %rax
movq 0x1c8(%rax), %rax
incq %rax
movq %rax, %xmm2
punpckldq %xmm4, %xmm2    # xmm2 = xmm2[0],xmm4[0],xmm2[1],xmm4[1]
subpd %xmm3, %xmm2
movaps %xmm2, %xmm3
unpckhpd %xmm2, %xmm2            # xmm2 = xmm2[1,1]
addsd %xmm3, %xmm2
mulsd %xmm2, %xmm1
ucomisd %xmm1, %xmm0
jne 0x15109
jp 0x15109
movq -0x28(%rbp), %rax
movq 0x368(%rax), %rdi
movq (%rdi), %rax
callq *0x10(%rax)
movq -0x28(%rbp), %rax
movq $0x0, 0x378(%rax)
movq 0x368(%rax), %rax
movq $0x0, 0x1c8(%rax)
movq -0x28(%rbp), %rax
movq 0x368(%rax), %rdi
movq (%rdi), %rax
callq *0x10(%rax)
jmp 0x1511c
movq -0x28(%rbp), %rax
leaq 0x51411(%rip), %rcx     # 0x66538
movsd (%rcx), %xmm0
movq 0x390(%rax), %xmm1
movaps 0x3bfe6(%rip), %xmm4    # 0x51120
punpckldq %xmm4, %xmm1    # xmm1 = xmm1[0],xmm4[0],xmm1[1],xmm4[1]
movapd 0x3bfea(%rip), %xmm3    # 0x51130
subpd %xmm3, %xmm1
movaps %xmm1, %xmm2
unpckhpd %xmm1, %xmm1            # xmm1 = xmm1[1,1]
addsd %xmm2, %xmm1
mulsd %xmm1, %xmm0
movsd 0x3a0(%rax), %xmm1
movq 0x398(%rax), %rax
incq %rax
movq %rax, %xmm2
punpckldq %xmm4, %xmm2    # xmm2 = xmm2[0],xmm4[0],xmm2[1],xmm4[1]
subpd %xmm3, %xmm2
movaps %xmm2, %xmm3
unpckhpd %xmm2, %xmm2            # xmm2 = xmm2[1,1]
addsd %xmm3, %xmm2
mulsd %xmm2, %xmm1
ucomisd %xmm1, %xmm0
jbe 0x1519a
movq -0x28(%rbp), %rdi
xorl %esi, %esi
callq 0x15c40
jmp 0x1511c
movq -0x28(%rbp), %rax
leaq 0x51393(%rip), %rcx     # 0x66538
movsd (%rcx), %xmm0
movq 0x390(%rax), %xmm1
movaps 0x3bf68(%rip), %xmm4    # 0x51120
punpckldq %xmm4, %xmm1    # xmm1 = xmm1[0],xmm4[0],xmm1[1],xmm4[1]
movapd 0x3bf6c(%rip), %xmm3    # 0x51130
subpd %xmm3, %xmm1
movaps %xmm1, %xmm2
unpckhpd %xmm1, %xmm1            # xmm1 = xmm1[1,1]
addsd %xmm2, %xmm1
mulsd %xmm1, %xmm0
movsd 0x3a0(%rax), %xmm1
movq 0x398(%rax), %rax
incq %rax
movq %rax, %xmm2
punpckldq %xmm4, %xmm2    # xmm2 = xmm2[0],xmm4[0],xmm2[1],xmm4[1]
subpd %xmm3, %xmm2
movaps %xmm2, %xmm3
unpckhpd %xmm2, %xmm2            # xmm2 = xmm2[1,1]
addsd %xmm3, %xmm2
mulsd %xmm2, %xmm1
ucomisd %xmm1, %xmm0
jne 0x15232
jp 0x15232
movq -0x28(%rbp), %rdi
xorl %esi, %esi
callq 0x15c40
movq -0x28(%rbp), %rax
movq $0x0, 0x390(%rax)
movq $0x0, 0x398(%rax)
movq -0x28(%rbp), %rdi
movl $0x1, %esi
callq 0x15c40
movl $0x0, -0x10(%rbp)
movl -0x10(%rbp), %eax
leaq 0x512f7(%rip), %rcx     # 0x66548
cmpl (%rcx), %eax
jge 0x15284
movq -0x28(%rbp), %rax
movq 0x330(%rax), %rdi
addq $0x220, %rdi            # imm = 0x220
movslq -0x10(%rbp), %rsi
callq 0x17790
movq (%rax), %rdi
movq (%rdi), %rax
callq *0x10(%rax)
movl -0x10(%rbp), %eax
addl $0x1, %eax
movl %eax, -0x10(%rbp)
jmp 0x15247
movq 0x50d45(%rip), %rdi     # 0x65fd0
movq 0x50d1e(%rip), %rsi     # 0x65fb0
callq 0x43c0
movq -0x28(%rbp), %rax
movq 0x330(%rax), %rdi
callq 0x3a2c0
movl $0x0, -0x14(%rbp)
movl -0x14(%rbp), %eax
leaq 0x51290(%rip), %rcx     # 0x66548
cmpl (%rcx), %eax
jge 0x152ea
movq -0x28(%rbp), %rax
movq 0x330(%rax), %rdi
addq $0x208, %rdi            # imm = 0x208
movslq -0x14(%rbp), %rsi
callq 0x17770
movq (%rax), %rdi
callq 0x3fa30
movl -0x14(%rbp), %eax
addl $0x1, %eax
movl %eax, -0x14(%rbp)
jmp 0x152ae
movl $0x0, -0x18(%rbp)
movl -0x18(%rbp), %eax
leaq 0x5124d(%rip), %rcx     # 0x66548
cmpl (%rcx), %eax
jge 0x15326
movq -0x28(%rbp), %rdi
addq $0x338, %rdi            # imm = 0x338
movslq -0x18(%rbp), %rsi
callq 0x17750
movq (%rax), %rdi
callq 0x3c100
movl -0x18(%rbp), %eax
addl $0x1, %eax
movl %eax, -0x18(%rbp)
jmp 0x152f1
movq -0x28(%rbp), %rax
movq 0x368(%rax), %rdi
callq 0x32380
movl $0x0, -0x1c(%rbp)
movl -0x1c(%rbp), %eax
leaq 0x51201(%rip), %rcx     # 0x66548
cmpl (%rcx), %eax
jge 0x15372
movq -0x28(%rbp), %rdi
addq $0x350, %rdi            # imm = 0x350
movslq -0x1c(%rbp), %rsi
callq 0x17750
movq (%rax), %rdi
callq 0x3c100
movl -0x1c(%rbp), %eax
addl $0x1, %eax
movl %eax, -0x1c(%rbp)
jmp 0x1533d
movl $0x0, -0x20(%rbp)
movl -0x20(%rbp), %eax
leaq 0x511c5(%rip), %rcx     # 0x66548
cmpl (%rcx), %eax
jge 0x153b5
movq -0x28(%rbp), %rax
movq 0x330(%rax), %rdi
addq $0x220, %rdi            # imm = 0x220
movslq -0x20(%rbp), %rsi
callq 0x17790
movq (%rax), %rdi
callq 0x434e0
movl -0x20(%rbp), %eax
addl $0x1, %eax
movl %eax, -0x20(%rbp)
jmp 0x15379
movq -0x28(%rbp), %rax
movq 0x370(%rax), %rcx
addq $0x1, %rcx
movq %rcx, 0x370(%rax)
movq 0x380(%rax), %rcx
addq $0x1, %rcx
movq %rcx, 0x380(%rax)
movq 0x390(%rax), %rcx
addq $0x1, %rcx
movq %rcx, 0x390(%rax)
movq 0x378(%rax), %rcx
addq $0x1, %rcx
movq %rcx, 0x378(%rax)
leaq 0x51120(%rip), %rax     # 0x66528
testb $0x1, (%rax)
jne 0x15419
leaq 0x51116(%rip), %rax     # 0x6652a
testb $0x1, (%rax)
je 0x15483
movq 0x50bb0(%rip), %rdi     # 0x65fd0
leaq 0x3c4a7(%rip), %rsi     # 0x518ce
callq 0x4380
movq %rax, %rdi
movq -0x28(%rbp), %rax
movq 0x370(%rax), %rsi
callq 0x40f0
movq %rax, %rdi
leaq 0x3c4b8(%rip), %rsi     # 0x51901
callq 0x4380
movq %rax, %rdi
movq -0x28(%rbp), %rax
movq 0x368(%rax), %rax
movq 0x8(%rax), %rsi
callq 0x40f0
movq %rax, %rdi
leaq 0x3c49e(%rip), %rsi     # 0x5190d
callq 0x4380
movq %rax, %rdi
movq 0x50b32(%rip), %rsi     # 0x65fb0
callq 0x43c0
addq $0x30, %rsp
popq %rbp
retq
nopl (%rax)