// File: /workspace/github_cpp_makefile_star2_O1/dramninjasUMD[P]BOBSim/LogicLayerInterface.cpp
// Function: BOBSim::LogicLayerInterface::Update()
void LogicLayerInterface::Update()
{
	//send back to channel if there is something in the outgoing queue
	if(outgoingQueue.size()>0 && (*ReturnToSimpleController)(outgoingQueue[0],0))
	{
		//if we just send the response, we are done and can clear the current stuff
		if(outgoingQueue[0]->transactionType==LOGIC_RESPONSE)
		{
			currentTransaction = NULL;
			currentLogicOperation = NULL;
		}

		outgoingQueue.erase(outgoingQueue.begin());
	}

	// if we aren't working on anything and there are logic ops waiting
	if (currentTransaction == NULL && !pendingLogicOpsQueue.empty())
	{
		//cast logic operation arguments from transaction
		if(pendingLogicOpsQueue[0]->logicOpContents != NULL)
		{

			//extract logic operation from transaction and grab handle to current operations
			currentLogicOperation = (LogicOperation *)pendingLogicOpsQueue[0]->logicOpContents;
			currentTransaction = pendingLogicOpsQueue[0];

			if(DEBUG_LOGIC) DEBUG(" == In logic layer "<<simpleControllerID<<" : interpreting transaction "<<*currentTransaction);

			// grabbed the pointers, now we can remove from queue
			pendingLogicOpsQueue.pop_front();


			//figure out what to do for each type
			switch(currentLogicOperation->logicType)
			{
			case LogicOperation::PAGE_FILL:
				//
				//Arguments:  1) Number of continuous pages
				//            2) Pattern to copy
				//
				uint64_t pageStart;
				uint64_t numPages;
				uint pattern;
				if(currentLogicOperation->arguments.size()!=2)
				{
					ERROR("== ERROR - Incorrect number of arguments for logic operation "<<currentLogicOperation->logicType);
					exit(-1);
				}

				//get arguments
				pageStart = currentTransaction->address;
				numPages = currentLogicOperation->arguments[0];
				pattern = (uint)currentLogicOperation->arguments[1];

				if(DEBUG_LOGIC)
				{
					DEBUG("       PAGE FILL");
					DEBUG("        Start     : "<<pageStart);
					DEBUG("        Num Pages : "<<numPages);
					DEBUG("        Fill with : "<<pattern);
				}

				//generate the writes required to write a pattern to each page
				for(int i=0; i<numPages; i++)
				{
					Transaction *trans = new Transaction(DATA_WRITE, 64, pageStart + i*(1<<(log2(BUS_ALIGNMENT_SIZE)+log2(NUM_CHANNELS))));
					trans->originatedFromLogicOp = true;

					if(DEBUG_LOGIC) DEBUG("      == Logic Op created : "<<*trans);

					outgoingQueue.push_back(trans);

					//pattern not used lol :(
				}

				//put the response at the back of the queue so when all the writes empty out, the response is ready to go
				currentTransaction->transactionType = LOGIC_RESPONSE;
				outgoingQueue.push_back(currentTransaction);

				break;
			case LogicOperation::MEM_COPY:
				//
				//Arguments : 1) Destination Address
				//            2) Size
				//

				uint64_t sourceAddress;
				uint64_t destinationAddress; //start of destination copy
				uint64_t sizeToCopy; //number of 64-byte words to copy
				if(currentLogicOperation->arguments.size()!=2)
				{
					ERROR("== ERROR - Incorrect number of arguments for logic operation "<<currentLogicOperation->logicType);
					exit(-1);
				}

				sourceAddress = currentTransaction->address;
				destinationAddress = currentLogicOperation->arguments[0];
				sizeToCopy = currentLogicOperation->arguments[1];

				if(DEBUG_LOGIC)
				{
					DEBUG("       MEM COPY");
					DEBUG("        Source Address      : 0x"<<hex<<setw(8)<<setfill('0')<<sourceAddress);
					DEBUG("        Dest Address        : 0x"<<hex<<setw(8)<<setfill('0')<<destinationAddress);
					DEBUG("        Size to copy (x64B) : "<<dec<<sizeToCopy);
				}

				for(int i=0; i<sizeToCopy; i++)
				{
					Transaction *trans = new Transaction(DATA_READ, 64, sourceAddress + i*(1<<(log2(BUS_ALIGNMENT_SIZE)+log2(NUM_CHANNELS))));
					trans->originatedFromLogicOp = true;

					if(DEBUG_LOGIC) DEBUG("      == Logic Op created : "<<*trans);

					outgoingQueue.push_back(trans);
				}

				break;
			case LogicOperation::PAGE_TABLE_WALK:
				uint64_t src_address;
				src_address = currentTransaction->address;
				for (size_t i=0; i<currentLogicOperation->arguments.size(); i++)
				{
					Transaction *trans = new Transaction(DATA_READ, 64, currentLogicOperation->arguments[i]);
					trans->originatedFromLogicOp = true;
					outgoingQueue.push_back(trans);
				}

				break;
			default:
				ERROR("== ERROR - Unknown logic type in logic layer : "<<currentLogicOperation->logicType);
				exit(-1);
			}

		}
		else
		{
			ERROR(" == Error - Logic operation has no contents : "<<*newOperationQueue[0]);
			exit(-1);
		}
	}


	//if we're getting data, it is probably from a logic op that generated requests
	if(!newOperationQueue.empty() && newOperationQueue[0]->transactionType == RETURN_DATA)
	{
		//
		//do some checks to ensure the data makes sense
		//
		if(currentTransaction==NULL)
		{
			ERROR("== ERROR - Getting data without a corresponding transaction");
			exit(-1);
		}

		if (DEBUG_LOGIC) DEBUG("   ==[L:"<<simpleControllerID<<"] oh hai, return data"<<*newOperationQueue[0]);
		//handle the return data based on the logic op that is being executed
		Transaction *t;
		switch(currentLogicOperation->logicType)
		{
		case LogicOperation::MEM_COPY:
			if (DEBUG_LOGIC) DEBUG(newOperationQueue[0]->address - currentTransaction->address);
			t = new Transaction(DATA_WRITE, 64, newOperationQueue[0]->address - currentTransaction->address + currentLogicOperation->arguments[0]);
			t->originatedFromLogicOp = true;

			if(DEBUG_LOGIC) DEBUG("      == Logic Op Copy moved data from 0x"<<hex<<setw(8)<<setfill('0')<<newOperationQueue[0]->address<<dec<<" to : "<<*t);

			outgoingQueue.push_back(t);

			issuedRequests++;

			newOperationQueue.erase(newOperationQueue.begin());

			//check to see if we are done with the requests
			if(issuedRequests==currentLogicOperation->arguments[1])
			{
				if(DEBUG_LOGIC) DEBUG("      == All WRITE commands issued for copy - creating response");

				//send back response
				currentTransaction->transactionType = LOGIC_RESPONSE;
				outgoingQueue.push_back(currentTransaction);
				issuedRequests = 0;
			}
			break;
		case LogicOperation::PAGE_TABLE_WALK:
			issuedRequests++;

			if (DEBUG_LOGIC) DEBUG("   ==[L:"<<simpleControllerID<<"] Getting back PT read for 0x"<<std::hex<<(newOperationQueue[0]->address)<<std::dec<<"("<<issuedRequests<<"/3)");

			//check to see if we are done with the requests
			if(issuedRequests == currentLogicOperation->arguments.size())
			{
				if(DEBUG_LOGIC) DEBUG("      ==[L:"<<simpleControllerID<<"] All walked all page table levels, - creating response");

				//send back response
				currentTransaction->transactionType = LOGIC_RESPONSE;
				outgoingQueue.push_back(currentTransaction);
				issuedRequests = 0;
			}
			newOperationQueue.erase(newOperationQueue.begin());

			break;

		default:
			ERROR("== ERROR - Getting data back for a logic op that doesnt create requests : "<<*currentTransaction);
			exit(-1);
			break;
		};
	}
	currentClockCycle++;
}

// Assembly:
pushq %rbp
pushq %r15
pushq %r14
pushq %r13
pushq %r12
pushq %rbx
subq $0x18, %rsp
movq %rdi, %rbx
leaq 0x90(%rdi), %r15
movq 0x90(%rdi), %rax
cmpq %rax, 0x98(%rdi)
je 0xe21c
movq (%rbx), %rdi
movq (%rax), %rsi
movq (%rdi), %rax
xorl %edx, %edx
callq *0x10(%rax)
testb %al, %al
je 0xe21c
movq (%r15), %rdi
movq (%rdi), %rax
cmpl $0x4, (%rax)
jne 0xe1fc
xorps %xmm0, %xmm0
movups %xmm0, 0x18(%rbx)
leaq 0x8(%rdi), %rsi
movq 0x98(%rbx), %rdx
cmpq %rdx, %rsi
je 0xe214
subq %rsi, %rdx
callq 0x32f0
addq $-0x8, 0x98(%rbx)
leaq 0x18(%rbx), %rax
movq %rax, 0x8(%rsp)
cmpq $0x0, 0x18(%rbx)
je 0xe2da
movq 0x78(%rbx), %r12
cmpq 0x80(%rbx), %r12
je 0xe6da
movq (%r12), %rax
cmpl $0x2, (%rax)
jne 0xe6da
movq 0x8(%rsp), %rax
movq (%rax), %r14
testq %r14, %r14
je 0xe6ff
movq 0x20(%rbx), %r13
movl (%r13), %eax
cmpl $0x2, %eax
je 0xe475
cmpl $0x1, %eax
jne 0xe7c2
movl $0x90, %edi
callq 0x31d0
movq (%r12), %rcx
movq 0x8(%rcx), %rcx
subq 0x8(%r14), %rcx
movq %rax, %r12
movq 0x8(%r13), %rax
addq (%rax), %rcx
movq %r12, %rdi
movl $0x1, %esi
movl $0x40, %edx
callq 0x123f0
movq %r12, 0x10(%rsp)
movb $0x1, 0x30(%r12)
movq 0x98(%rbx), %rsi
cmpq 0xa0(%rbx), %rsi
je 0xe614
movq %r12, (%rsi)
addq $0x8, 0x98(%rbx)
jmp 0xe621
movq 0x38(%rbx), %rdx
cmpq %rdx, 0x58(%rbx)
je 0xe230
movq %rdx, %rax
subq 0x40(%rbx), %rax
movabsq $-0x400000000000000, %rcx # imm = 0xFC00000000000000
sarq $0x3, %rax
movq %rdx, %rsi
cmpq $0x40, %rax
jb 0xe333
movq %rax, %rsi
shrq $0x6, %rsi
movq %rsi, %rdi
orq %rcx, %rdi
testq %rax, %rax
cmovgq %rsi, %rdi
movq 0x50(%rbx), %r8
movq %rdi, %r9
shlq $0x6, %r9
movq %rax, %rsi
subq %r9, %rsi
shlq $0x3, %rsi
addq (%r8,%rdi,8), %rsi
movq (%rsi), %rsi
cmpq $0x0, 0x28(%rsi)
je 0xe760
movq %rdx, %rsi
cmpq $0x40, %rax
jb 0xe377
movq %rax, %rsi
shrq $0x6, %rsi
movq %rsi, %rdi
orq %rcx, %rdi
testq %rax, %rax
cmovgq %rsi, %rdi
movq 0x50(%rbx), %r8
movq %rdi, %r9
shlq $0x6, %r9
movq %rax, %rsi
subq %r9, %rsi
shlq $0x3, %rsi
addq (%r8,%rdi,8), %rsi
leaq 0x28(%rbx), %rdi
movq (%rsi), %rsi
movq 0x28(%rsi), %rsi
movq %rsi, 0x20(%rbx)
cmpq $0x40, %rax
jb 0xe3b6
movq %rax, %rdx
shrq $0x6, %rdx
orq %rdx, %rcx
testq %rax, %rax
cmovgq %rdx, %rcx
movq 0x50(%rbx), %rdx
movq %rcx, %rsi
shlq $0x6, %rsi
subq %rsi, %rax
shlq $0x3, %rax
addq (%rdx,%rcx,8), %rax
movq %rax, %rdx
movq (%rdx), %rax
movq %rax, 0x18(%rbx)
callq 0xe96c
movq 0x20(%rbx), %rax
movl (%rax), %ecx
testl %ecx, %ecx
je 0xe558
cmpl $0x1, %ecx
je 0xe4c3
cmpl $0x2, %ecx
jne 0xe833
movq 0x20(%rbx), %r14
movq 0x10(%r14), %rax
cmpq 0x8(%r14), %rax
je 0xe230
addq $0x8, %r14
xorl %ebp, %ebp
leaq 0x10(%rsp), %r12
movl $0x90, %edi
callq 0x31d0
movq %rax, %r13
movq (%r14), %rax
movq (%rax,%rbp,8), %rcx
movq %r13, %rdi
xorl %esi, %esi
movl $0x40, %edx
callq 0x123f0
movq %r13, 0x10(%rsp)
movb $0x1, 0x30(%r13)
movq 0x98(%rbx), %rsi
cmpq 0xa0(%rbx), %rsi
je 0xe449
movq %r13, (%rsi)
addq $0x8, 0x98(%rbx)
jmp 0xe454
movq %r15, %rdi
movq %r12, %rdx
callq 0x7e56
incq %rbp
movq 0x20(%rbx), %rax
leaq 0x8(%rax), %r14
movq 0x10(%rax), %rcx
subq 0x8(%rax), %rcx
sarq $0x3, %rcx
cmpq %rcx, %rbp
jb 0xe3ff
jmp 0xe230
movl 0xa8(%rbx), %eax
incl %eax
movl %eax, 0xa8(%rbx)
movq 0x10(%r13), %rcx
subq 0x8(%r13), %rcx
sarq $0x3, %rcx
cmpq %rax, %rcx
jne 0xe69d
movl $0x4, (%r14)
movq 0x98(%rbx), %rsi
cmpq 0xa0(%rbx), %rsi
je 0xe686
movq %r14, (%rsi)
addq $0x8, 0x98(%rbx)
jmp 0xe693
movq 0x8(%rax), %rcx
movq 0x10(%rax), %rax
subq %rcx, %rax
cmpq $0x10, %rax
jne 0xe88c
movq 0x8(%rcx), %rbp
testq %rbp, %rbp
je 0xe230
movq 0x8(%rsp), %rax
movq (%rax), %rax
movq 0x8(%rax), %r14
xorl %r12d, %r12d
movl $0x90, %edi
callq 0x31d0
movq %rax, %r13
movslq %r12d, %rcx
addq %r14, %rcx
movq %rax, %rdi
xorl %esi, %esi
movl $0x40, %edx
callq 0x123f0
movq %r13, 0x10(%rsp)
movb $0x1, 0x30(%r13)
movq 0x98(%rbx), %rsi
cmpq 0xa0(%rbx), %rsi
je 0xe53d
movq %r13, (%rsi)
addq $0x8, 0x98(%rbx)
jmp 0xe54a
movq %r15, %rdi
leaq 0x10(%rsp), %rdx
callq 0x7e56
addl $0x40, %r12d
decq %rbp
jne 0xe4f4
jmp 0xe230
movq 0x8(%rax), %rcx
movq 0x10(%rax), %rax
subq %rcx, %rax
cmpq $0x10, %rax
jne 0xe8c7
movq (%rcx), %rbp
testq %rbp, %rbp
je 0xe5e6
movq 0x8(%rsp), %rax
movq (%rax), %rax
movq 0x8(%rax), %r14
xorl %r12d, %r12d
movl $0x90, %edi
callq 0x31d0
movq %rax, %r13
movslq %r12d, %rcx
addq %r14, %rcx
movq %rax, %rdi
movl $0x1, %esi
movl $0x40, %edx
callq 0x123f0
movq %r13, 0x10(%rsp)
movb $0x1, 0x30(%r13)
movq 0x98(%rbx), %rsi
cmpq 0xa0(%rbx), %rsi
je 0xe5d0
movq %r13, (%rsi)
addq $0x8, 0x98(%rbx)
jmp 0xe5dd
movq %r15, %rdi
leaq 0x10(%rsp), %rdx
callq 0x7e56
addl $0x40, %r12d
decq %rbp
jne 0xe584
movq 0x18(%rbx), %rax
movl $0x4, (%rax)
movq 0x98(%rbx), %rsi
cmpq 0xa0(%rbx), %rsi
je 0xe6ed
movq %rax, (%rsi)
addq $0x8, 0x98(%rbx)
jmp 0xe230
leaq 0x10(%rsp), %rdx
movq %r15, %rdi
callq 0x7e56
incl 0xa8(%rbx)
movq 0x78(%rbx), %rdi
movq 0x80(%rbx), %rdx
leaq 0x8(%rdi), %rsi
cmpq %rdx, %rsi
je 0xe643
subq %rsi, %rdx
callq 0x32f0
addq $-0x8, 0x80(%rbx)
movl 0xa8(%rbx), %eax
movq 0x20(%rbx), %rcx
movq 0x8(%rcx), %rcx
cmpq %rax, 0x8(%rcx)
jne 0xe6da
movq 0x18(%rbx), %rax
movl $0x4, (%rax)
movq 0x98(%rbx), %rsi
cmpq 0xa0(%rbx), %rsi
je 0xe6c3
movq %rax, (%rsi)
addq $0x8, 0x98(%rbx)
jmp 0xe6d0
movq %r15, %rdi
movq 0x8(%rsp), %rdx
callq 0x7e56
movl $0x0, 0xa8(%rbx)
movq 0x78(%rbx), %rdi
movq 0x80(%rbx), %rdx
leaq 0x8(%rdi), %rsi
cmpq %rdx, %rsi
je 0xe6b9
subq %rsi, %rdx
callq 0x32f0
addq $-0x8, 0x80(%rbx)
jmp 0xe6da
movq %r15, %rdi
movq 0x8(%rsp), %rdx
callq 0x7e56
movl $0x0, 0xa8(%rbx)
incq 0x10(%rbx)
addq $0x18, %rsp
popq %rbx
popq %r12
popq %r13
popq %r14
popq %r15
popq %rbp
retq
movq %r15, %rdi
movq 0x8(%rsp), %rdx
callq 0x7e56
jmp 0xe230
movq 0xa8ea(%rip), %rdi      # 0x18ff0
leaq 0x4a6b(%rip), %rsi      # 0x13178
callq 0x31c0
leaq 0x5e57(%rip), %rsi      # 0x14570
movq %rax, %rdi
callq 0x31c0
leaq 0x49f9(%rip), %rsi      # 0x13121
movq %rax, %rdi
callq 0x31c0
movq %rax, %rdi
movl $0xd7, %esi
callq 0x3330
leaq 0x4a45(%rip), %rsi      # 0x13189
movq %rax, %rdi
callq 0x31c0
leaq 0x5ed2(%rip), %rsi      # 0x14625
movq %rax, %rdi
callq 0x31c0
jmp 0xe931
movq 0xa889(%rip), %rdi      # 0x18ff0
leaq 0x4a0a(%rip), %rsi      # 0x13178
callq 0x31c0
leaq 0x5df6(%rip), %rsi      # 0x14570
movq %rax, %rdi
callq 0x31c0
leaq 0x4998(%rip), %rsi      # 0x13121
movq %rax, %rdi
callq 0x31c0
movq %rax, %rdi
movl $0xc9, %esi
callq 0x3330
leaq 0x49e4(%rip), %rsi      # 0x13189
movq %rax, %rdi
callq 0x31c0
leaq 0x5e42(%rip), %rsi      # 0x145f6
movq %rax, %rdi
callq 0x31c0
movq 0x78(%rbx), %rcx
jmp 0xe823
movq 0xa827(%rip), %rdi      # 0x18ff0
leaq 0x49a8(%rip), %rsi      # 0x13178
callq 0x31c0
leaq 0x5d94(%rip), %rsi      # 0x14570
movq %rax, %rdi
callq 0x31c0
leaq 0x4936(%rip), %rsi      # 0x13121
movq %rax, %rdi
callq 0x31c0
movq %rax, %rdi
movl $0x10c, %esi            # imm = 0x10C
callq 0x3330
leaq 0x4982(%rip), %rsi      # 0x13189
movq %rax, %rdi
callq 0x31c0
leaq 0x5e4b(%rip), %rsi      # 0x14661
movq %rax, %rdi
callq 0x31c0
movq 0x8(%rsp), %rcx
movq (%rcx), %rsi
movq %rax, %rdi
callq 0x1243b
jmp 0xe931
movq 0xa7b6(%rip), %rdi      # 0x18ff0
leaq 0x4937(%rip), %rsi      # 0x13178
callq 0x31c0
leaq 0x5d23(%rip), %rsi      # 0x14570
movq %rax, %rdi
callq 0x31c0
leaq 0x48c5(%rip), %rsi      # 0x13121
movq %rax, %rdi
callq 0x31c0
movq %rax, %rdi
movl $0xc2, %esi
callq 0x3330
leaq 0x4911(%rip), %rsi      # 0x13189
movq %rax, %rdi
callq 0x31c0
leaq 0x5d3f(%rip), %rsi      # 0x145c6
jmp 0xe91b
movq 0xa75d(%rip), %rdi      # 0x18ff0
leaq 0x48de(%rip), %rsi      # 0x13178
callq 0x31c0
leaq 0x5cca(%rip), %rsi      # 0x14570
movq %rax, %rdi
callq 0x31c0
leaq 0x486c(%rip), %rsi      # 0x13121
movq %rax, %rdi
callq 0x31c0
movq %rax, %rdi
movl $0x9b, %esi
jmp 0xe900
movq 0xa722(%rip), %rdi      # 0x18ff0
leaq 0x48a3(%rip), %rsi      # 0x13178
callq 0x31c0
leaq 0x5c8f(%rip), %rsi      # 0x14570
movq %rax, %rdi
callq 0x31c0
leaq 0x4831(%rip), %rsi      # 0x13121
movq %rax, %rdi
callq 0x31c0
movq %rax, %rdi
movl $0x6d, %esi
callq 0x3330
leaq 0x487d(%rip), %rsi      # 0x13189
movq %rax, %rdi
callq 0x31c0
leaq 0x5c6d(%rip), %rsi      # 0x14588
movq %rax, %rdi
callq 0x31c0
movq 0x20(%rbx), %rcx
movl (%rcx), %esi
movq %rax, %rdi
callq 0x3330
movq %rax, %rdi
callq 0x30d0
movl $0xffffffff, %edi       # imm = 0xFFFFFFFF
callq 0x3220
movq %rax, %rbx
movl $0x90, %esi
movq %r12, %rdi
jmp 0xe95f
jmp 0xe954
jmp 0xe954
movq %rax, %rbx
movl $0x90, %esi
movq %r13, %rdi
callq 0x31f0
movq %rbx, %rdi
callq 0x3340