// File: /workspace/github_cpp_makefile_star2_O2/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 %r15
pushq %r14
pushq %r12
pushq %rbx
pushq %rax
movq %rdi, %rbx
leaq 0x24e08(%rip), %rax     # 0x31490
cmpb $0x1, (%rax)
jne 0xc6b5
movq 0x370(%rbx), %rax
testq %rax, %rax
je 0xc6b5
leaq 0x24dec(%rip), %rcx     # 0x3148c
movslq (%rcx), %rcx
xorl %edx, %edx
divq %rcx
testq %rdx, %rdx
jne 0xc6b5
movq %rbx, %rdi
callq 0xcad2
movq 0x330(%rbx), %rdi
movq (%rdi), %rax
callq *0x10(%rax)
xorl %r15d, %r15d
leaq 0x24ddc(%rip), %r14     # 0x314a8
movslq (%r14), %rax
cmpq %rax, %r15
jge 0xc6f1
movq 0x330(%rbx), %rax
movq 0x208(%rax), %rax
movq (%rax,%r15,8), %rdi
movq (%rdi), %rax
callq *0x10(%rax)
incq %r15
jmp 0xc6cc
leaq 0x380(%rbx), %r12
leaq 0x24d99(%rip), %r15     # 0x31498
movsd 0x380(%rbx), %xmm0
movsd 0x17a21(%rip), %xmm2    # 0x24130
unpcklps %xmm2, %xmm0            # xmm0 = xmm0[0],xmm2[0],xmm0[1],xmm2[1]
movapd 0x17a26(%rip), %xmm3    # 0x24140
subpd %xmm3, %xmm0
movapd %xmm0, %xmm1
unpckhpd %xmm0, %xmm1            # xmm1 = xmm1[1],xmm0[1]
addsd %xmm0, %xmm1
mulsd (%r15), %xmm1
movq 0x388(%rbx), %rax
incq %rax
movq %rax, %xmm0
punpckldq %xmm2, %xmm0    # xmm0 = xmm0[0],xmm2[0],xmm0[1],xmm2[1]
subpd %xmm3, %xmm0
movapd %xmm0, %xmm2
unpckhpd %xmm0, %xmm2            # xmm2 = xmm2[1],xmm0[1]
addsd %xmm0, %xmm2
mulsd 0x3a0(%rbx), %xmm2
ucomisd %xmm2, %xmm1
jbe 0xc76c
movq %rbx, %rdi
xorl %esi, %esi
callq 0xcdaa
jmp 0xc6ff
jne 0xc784
jp 0xc784
movq %rbx, %rdi
xorl %esi, %esi
callq 0xcdaa
xorpd %xmm0, %xmm0
movupd %xmm0, (%r12)
pushq $0x1
popq %rsi
movq %rbx, %rdi
callq 0xcdaa
movsd (%r15), %xmm1
leaq 0x24e05(%rip), %r12     # 0x315a0
movsd (%r12), %xmm0
ucomisd %xmm1, %xmm0
jae 0xc81d
movsd 0x378(%rbx), %xmm2
movsd 0x17979(%rip), %xmm4    # 0x24130
unpcklps %xmm4, %xmm2            # xmm2 = xmm2[0],xmm4[0],xmm2[1],xmm4[1]
movapd 0x1797e(%rip), %xmm5    # 0x24140
subpd %xmm5, %xmm2
movapd %xmm2, %xmm3
unpckhpd %xmm2, %xmm3            # xmm3 = xmm3[1],xmm2[1]
addsd %xmm2, %xmm3
mulsd %xmm1, %xmm3
movq 0x368(%rbx), %rdi
movq 0x1c8(%rdi), %rax
incq %rax
movq %rax, %xmm1
punpckldq %xmm4, %xmm1    # xmm1 = xmm1[0],xmm4[0],xmm1[1],xmm4[1]
subpd %xmm5, %xmm1
movapd %xmm1, %xmm2
unpckhpd %xmm1, %xmm2            # xmm2 = xmm2[1],xmm1[1]
addsd %xmm1, %xmm2
mulsd %xmm0, %xmm2
ucomisd %xmm2, %xmm3
jbe 0xc886
movq (%rdi), %rax
callq *0x10(%rax)
movsd (%r15), %xmm1
movsd (%r12), %xmm0
jmp 0xc7a7
movsd 0x378(%rbx), %xmm2
movsd 0x17903(%rip), %xmm4    # 0x24130
unpcklps %xmm4, %xmm2            # xmm2 = xmm2[0],xmm4[0],xmm2[1],xmm4[1]
movapd 0x17908(%rip), %xmm5    # 0x24140
subpd %xmm5, %xmm2
movapd %xmm2, %xmm3
unpckhpd %xmm2, %xmm3            # xmm3 = xmm3[1],xmm2[1]
addsd %xmm2, %xmm3
mulsd %xmm3, %xmm1
movq 0x368(%rbx), %rdi
movsd 0x1c8(%rdi), %xmm2
unpcklps %xmm4, %xmm2            # xmm2 = xmm2[0],xmm4[0],xmm2[1],xmm4[1]
subpd %xmm5, %xmm2
movapd %xmm2, %xmm3
unpckhpd %xmm2, %xmm3            # xmm3 = xmm3[1],xmm2[1]
addsd %xmm2, %xmm3
mulsd %xmm3, %xmm0
ucomisd %xmm0, %xmm1
ja 0xc8a7
jne 0xc8ad
jp 0xc8ad
andq $0x0, 0x378(%rbx)
jmp 0xc89f
jne 0xc8a7
jp 0xc8a7
movq (%rdi), %rax
callq *0x10(%rax)
andq $0x0, 0x378(%rbx)
movq 0x368(%rbx), %rdi
andq $0x0, 0x1c8(%rdi)
movq (%rdi), %rax
callq *0x10(%rax)
leaq 0x390(%rbx), %r12
movsd 0x390(%rbx), %xmm0
movsd 0x1786c(%rip), %xmm2    # 0x24130
unpcklps %xmm2, %xmm0            # xmm0 = xmm0[0],xmm2[0],xmm0[1],xmm2[1]
movapd 0x17871(%rip), %xmm3    # 0x24140
subpd %xmm3, %xmm0
movapd %xmm0, %xmm1
unpckhpd %xmm0, %xmm1            # xmm1 = xmm1[1],xmm0[1]
addsd %xmm0, %xmm1
mulsd (%r15), %xmm1
movq 0x398(%rbx), %rax
incq %rax
movq %rax, %xmm0
punpckldq %xmm2, %xmm0    # xmm0 = xmm0[0],xmm2[0],xmm0[1],xmm2[1]
subpd %xmm3, %xmm0
movapd %xmm0, %xmm2
unpckhpd %xmm0, %xmm2            # xmm2 = xmm2[1],xmm0[1]
addsd %xmm0, %xmm2
mulsd 0x3a0(%rbx), %xmm2
ucomisd %xmm2, %xmm1
jbe 0xc921
movq %rbx, %rdi
xorl %esi, %esi
callq 0xcdf4
jmp 0xc8b4
jne 0xc939
jp 0xc939
movq %rbx, %rdi
xorl %esi, %esi
callq 0xcdf4
xorpd %xmm0, %xmm0
movupd %xmm0, (%r12)
pushq $0x1
popq %rsi
movq %rbx, %rdi
callq 0xcdf4
xorl %r15d, %r15d
movslq (%r14), %rax
cmpq %rax, %r15
jge 0xc96c
movq 0x330(%rbx), %rax
movq 0x220(%rax), %rax
movq (%rax,%r15,8), %rdi
movq (%rdi), %rax
callq *0x10(%rax)
incq %r15
jmp 0xc947
movq 0x2465d(%rip), %rdi     # 0x30fd0
callq 0x4180
movq 0x330(%rbx), %rdi
callq 0x190f8
xorl %r15d, %r15d
movslq (%r14), %rax
cmpq %rax, %r15
jge 0xc9ab
movq 0x330(%rbx), %rax
movq 0x208(%rax), %rax
movq (%rax,%r15,8), %rdi
callq 0x1bfac
incq %r15
jmp 0xc987
xorl %r15d, %r15d
cltq
cmpq %rax, %r15
jge 0xc9cd
movq 0x338(%rbx), %rax
movq (%rax,%r15,8), %rdi
callq 0x19e16
incq %r15
movl (%r14), %eax
jmp 0xc9ae
movq 0x368(%rbx), %rdi
callq 0x15c84
xorl %r15d, %r15d
movslq (%r14), %rax
cmpq %rax, %r15
jge 0xc9f9
movq 0x350(%rbx), %rax
movq (%rax,%r15,8), %rdi
callq 0x19e16
incq %r15
jmp 0xc9dc
xorl %r15d, %r15d
cltq
cmpq %rax, %r15
jge 0xca22
movq 0x330(%rbx), %rax
movq 0x220(%rax), %rax
movq (%rax,%r15,8), %rdi
callq 0x1d9d2
incq %r15
movl (%r14), %eax
jmp 0xc9fc
incq 0x380(%rbx)
incq 0x390(%rbx)
movdqu 0x370(%rbx), %xmm0
pcmpeqd %xmm1, %xmm1
psubq %xmm1, %xmm0
movdqu %xmm0, 0x370(%rbx)
leaq 0x24a39(%rip), %rax     # 0x31488
cmpb $0x0, (%rax)
jne 0xca60
leaq 0x24a2f(%rip), %rax     # 0x3148a
cmpb $0x1, (%rax)
jne 0xcac6
movq 0x24569(%rip), %rdi     # 0x30fd0
leaq 0x17ea2(%rip), %rsi     # 0x24910
callq 0x4300
movq 0x370(%rbx), %rsi
movq %rax, %rdi
callq 0x4210
leaq 0x17eba(%rip), %rsi     # 0x24943
movq %rax, %rdi
callq 0x4300
movq 0x368(%rbx), %rcx
movq 0x8(%rcx), %rsi
movq %rax, %rdi
callq 0x4210
leaq 0x17ea4(%rip), %rsi     # 0x2494f
movq %rax, %rdi
callq 0x4300
movq %rax, %rdi
addq $0x8, %rsp
popq %rbx
popq %r12
popq %r14
popq %r15
jmp 0x4180
addq $0x8, %rsp
popq %rbx
popq %r12
popq %r14
popq %r15
retq