// File: /workspace/github_cpp_makefile_star2_O3/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), %r14
movq 0x90(%rdi), %rax
cmpq %rax, 0x98(%rdi)
je 0xdffe
movq (%rbx), %rdi
movq (%rax), %rsi
movq (%rdi), %rax
xorl %edx, %edx
callq *0x10(%rax)
testb %al, %al
je 0xdffe
movq (%r14), %rdi
movq (%rdi), %rax
cmpl $0x4, (%rax)
jne 0xdfd4
xorps %xmm0, %xmm0
movups %xmm0, 0x18(%rbx)
leaq 0x8(%rdi), %rsi
movq 0x98(%rbx), %rdx
cmpq %rdx, %rsi
je 0xdff3
subq %rsi, %rdx
callq 0x32f0
movq 0x98(%rbx), %rdx
addq $-0x8, %rdx
movq %rdx, 0x98(%rbx)
leaq 0x18(%rbx), %rax
movq %rax, 0x8(%rsp)
cmpq $0x0, 0x18(%rbx)
je 0xe0bd
movq 0x78(%rbx), %rdi
movq 0x80(%rbx), %rdx
cmpq %rdx, %rdi
je 0xe4bf
movq (%rdi), %r12
cmpl $0x2, (%r12)
jne 0xe4bf
movq 0x8(%rsp), %rax
movq (%rax), %r15
testq %r15, %r15
je 0xe4e4
movq 0x20(%rbx), %r13
movl (%r13), %eax
cmpl $0x2, %eax
je 0xe106
cmpl $0x1, %eax
jne 0xe5a7
movl $0x90, %edi
callq 0x31d0
movq 0x8(%r12), %rcx
subq 0x8(%r15), %rcx
movq %rax, %r12
movq 0x8(%r13), %rax
addq (%rax), %rcx
movq %r12, %rdi
movl $0x1, %esi
movl $0x40, %edx
callq 0x122bc
movq %r12, 0x10(%rsp)
movb $0x1, 0x30(%r12)
movq 0x98(%rbx), %rsi
cmpq 0xa0(%rbx), %rsi
je 0xe3d7
movq %r12, (%rsi)
addq $0x8, 0x98(%rbx)
jmp 0xe3e4
movq 0x38(%rbx), %rsi
cmpq %rsi, 0x58(%rbx)
je 0xe012
movq 0x50(%rbx), %rax
movq %rsi, %rdx
subq 0x40(%rbx), %rdx
movq %rdx, %rcx
sarq $0x3, %rcx
js 0xe154
cmpq $0x40, %rcx
jae 0xe181
movq (%rsi), %rax
movq 0x28(%rax), %rax
testq %rax, %rax
je 0xe545
leaq 0x20(%rbx), %rbp
movq %rax, 0x20(%rbx)
jmp 0xe1b8
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 0xe483
movl $0x4, (%r15)
movq 0x98(%rbx), %rsi
cmpq 0xa0(%rbx), %rsi
je 0xe461
movq %r15, (%rsi)
addq $0x8, 0x98(%rbx)
jmp 0xe46e
sarq $0x9, %rdx
movq (%rax,%rdx,8), %rsi
movq %rdx, %rdi
shlq $0x6, %rdi
subq %rdi, %rcx
movq (%rsi,%rcx,8), %rsi
movq 0x28(%rsi), %rsi
testq %rsi, %rsi
je 0xe545
leaq 0x20(%rbx), %rbp
movq %rsi, 0x20(%rbx)
jmp 0xe1ad
movq %rcx, %rdx
shrq $0x6, %rdx
movq (%rax,%rdx,8), %rsi
movl %ecx, %edi
andl $0x3f, %edi
movq (%rsi,%rdi,8), %rsi
movq 0x28(%rsi), %rsi
testq %rsi, %rsi
je 0xe545
leaq 0x20(%rbx), %rbp
movq %rsi, 0x20(%rbx)
andl $0x3f, %ecx
shlq $0x3, %rcx
addq (%rax,%rdx,8), %rcx
movq %rcx, %rsi
leaq 0x28(%rbx), %rdi
movq (%rsi), %rax
movq 0x8(%rsp), %rcx
movq %rax, (%rcx)
callq 0xe752
movq (%rbp), %r12
movl (%r12), %eax
testl %eax, %eax
je 0xe315
cmpl $0x1, %eax
je 0xe27e
cmpl $0x2, %eax
jne 0xe618
movq 0x10(%r12), %rax
cmpq 0x8(%r12), %rax
je 0xe012
addq $0x8, %r12
xorl %r15d, %r15d
movl $0x90, %edi
callq 0x31d0
movq %rax, %r13
movq (%r12), %rax
movq (%rax,%r15,8), %rcx
movq %r13, %rdi
xorl %esi, %esi
movl $0x40, %edx
callq 0x122bc
movq %r13, 0x10(%rsp)
movb $0x1, 0x30(%r13)
movq 0x98(%rbx), %rsi
cmpq 0xa0(%rbx), %rsi
je 0xe250
movq %r13, (%rsi)
addq $0x8, 0x98(%rbx)
jmp 0xe25d
movq %r14, %rdi
leaq 0x10(%rsp), %rdx
callq 0x7b4c
incq %r15
movq (%rbp), %rax
leaq 0x8(%rax), %r12
movq 0x10(%rax), %rcx
subq 0x8(%rax), %rcx
sarq $0x3, %rcx
cmpq %rcx, %r15
jb 0xe205
jmp 0xe012
movq 0x8(%r12), %rax
movq 0x10(%r12), %rcx
subq %rax, %rcx
cmpq $0x10, %rcx
jne 0xe671
movq 0x8(%rax), %rbp
testq %rbp, %rbp
je 0xe012
movq 0x8(%rsp), %rax
movq (%rax), %rax
movq 0x8(%rax), %r15
xorl %r12d, %r12d
movl $0x90, %edi
callq 0x31d0
movq %rax, %r13
movslq %r12d, %rcx
addq %r15, %rcx
movq %rax, %rdi
xorl %esi, %esi
movl $0x40, %edx
callq 0x122bc
movq %r13, 0x10(%rsp)
movb $0x1, 0x30(%r13)
movq 0x98(%rbx), %rsi
cmpq 0xa0(%rbx), %rsi
je 0xe2fa
movq %r13, (%rsi)
addq $0x8, 0x98(%rbx)
jmp 0xe307
movq %r14, %rdi
leaq 0x10(%rsp), %rdx
callq 0x7b4c
addl $0x40, %r12d
decq %rbp
jne 0xe2b1
jmp 0xe012
movq 0x8(%r12), %rcx
movq 0x10(%r12), %rax
subq %rcx, %rax
cmpq $0x10, %rax
jne 0xe6ac
movq 0x8(%rsp), %rax
movq (%rax), %rax
movq (%rcx), %rbp
testq %rbp, %rbp
je 0xe3ad
movq 0x8(%rax), %r15
xorl %r12d, %r12d
movl $0x90, %edi
callq 0x31d0
movq %rax, %r13
movslq %r12d, %rcx
addq %r15, %rcx
movq %rax, %rdi
movl $0x1, %esi
movl $0x40, %edx
callq 0x122bc
movq %r13, 0x10(%rsp)
movb $0x1, 0x30(%r13)
movq 0x98(%rbx), %rsi
cmpq 0xa0(%rbx), %rsi
je 0xe38f
movq %r13, (%rsi)
addq $0x8, 0x98(%rbx)
jmp 0xe39c
movq %r14, %rdi
leaq 0x10(%rsp), %rdx
callq 0x7b4c
addl $0x40, %r12d
decq %rbp
jne 0xe343
movq 0x8(%rsp), %rax
movq (%rax), %rax
movl $0x4, (%rax)
movq 0x98(%rbx), %rsi
cmpq 0xa0(%rbx), %rsi
je 0xe4d2
movq %rax, (%rsi)
addq $0x8, 0x98(%rbx)
jmp 0xe012
leaq 0x10(%rsp), %rdx
movq %r14, %rdi
callq 0x7b4c
movl 0xa8(%rbx), %eax
incl %eax
movl %eax, 0xa8(%rbx)
movq 0x78(%rbx), %rdi
movq 0x80(%rbx), %rdx
leaq 0x8(%rdi), %rsi
cmpq %rdx, %rsi
je 0xe41b
subq %rsi, %rdx
callq 0x32f0
movq 0x80(%rbx), %rdx
movl 0xa8(%rbx), %eax
addq $-0x8, %rdx
movq %rdx, 0x80(%rbx)
movl %eax, %eax
movq 0x20(%rbx), %rcx
movq 0x8(%rcx), %rcx
cmpq %rax, 0x8(%rcx)
jne 0xe4bf
movq 0x18(%rbx), %rax
movl $0x4, (%rax)
movq 0x98(%rbx), %rsi
cmpq 0xa0(%rbx), %rsi
je 0xe4a8
movq %rax, (%rsi)
addq $0x8, 0x98(%rbx)
jmp 0xe4b5
movq %r14, %rdi
movq 0x8(%rsp), %rdx
callq 0x7b4c
movl $0x0, 0xa8(%rbx)
movq 0x78(%rbx), %rdi
movq 0x80(%rbx), %rdx
leaq 0x8(%rdi), %rsi
cmpq %rdx, %rsi
je 0xe49b
subq %rsi, %rdx
callq 0x32f0
movq 0x80(%rbx), %rdx
addq $-0x8, %rdx
movq %rdx, 0x80(%rbx)
jmp 0xe4bf
movq %r14, %rdi
movq 0x8(%rsp), %rdx
callq 0x7b4c
movl $0x0, 0xa8(%rbx)
incq 0x10(%rbx)
addq $0x18, %rsp
popq %rbx
popq %r12
popq %r13
popq %r14
popq %r15
popq %rbp
retq
movq %r14, %rdi
movq 0x8(%rsp), %rdx
callq 0x7b4c
jmp 0xe012
movq 0xab05(%rip), %rdi      # 0x18ff0
leaq 0x4cd6(%rip), %rsi      # 0x131c8
callq 0x31c0
leaq 0x6112(%rip), %rsi      # 0x14610
movq %rax, %rdi
callq 0x31c0
leaq 0x4c64(%rip), %rsi      # 0x13171
movq %rax, %rdi
callq 0x31c0
movq %rax, %rdi
movl $0xd7, %esi
callq 0x3330
leaq 0x4cb0(%rip), %rsi      # 0x131d9
movq %rax, %rdi
callq 0x31c0
leaq 0x618d(%rip), %rsi      # 0x146c5
movq %rax, %rdi
callq 0x31c0
jmp 0xe716
movq 0xaaa4(%rip), %rdi      # 0x18ff0
leaq 0x4c75(%rip), %rsi      # 0x131c8
callq 0x31c0
leaq 0x60b1(%rip), %rsi      # 0x14610
movq %rax, %rdi
callq 0x31c0
leaq 0x4c03(%rip), %rsi      # 0x13171
movq %rax, %rdi
callq 0x31c0
movq %rax, %rdi
movl $0xc9, %esi
callq 0x3330
leaq 0x4c4f(%rip), %rsi      # 0x131d9
movq %rax, %rdi
callq 0x31c0
leaq 0x60fd(%rip), %rsi      # 0x14696
movq %rax, %rdi
callq 0x31c0
movq 0x78(%rbx), %rcx
jmp 0xe608
movq 0xaa42(%rip), %rdi      # 0x18ff0
leaq 0x4c13(%rip), %rsi      # 0x131c8
callq 0x31c0
leaq 0x604f(%rip), %rsi      # 0x14610
movq %rax, %rdi
callq 0x31c0
leaq 0x4ba1(%rip), %rsi      # 0x13171
movq %rax, %rdi
callq 0x31c0
movq %rax, %rdi
movl $0x10c, %esi            # imm = 0x10C
callq 0x3330
leaq 0x4bed(%rip), %rsi      # 0x131d9
movq %rax, %rdi
callq 0x31c0
leaq 0x6106(%rip), %rsi      # 0x14701
movq %rax, %rdi
callq 0x31c0
movq 0x8(%rsp), %rcx
movq (%rcx), %rsi
movq %rax, %rdi
callq 0x12307
jmp 0xe716
movq 0xa9d1(%rip), %rdi      # 0x18ff0
leaq 0x4ba2(%rip), %rsi      # 0x131c8
callq 0x31c0
leaq 0x5fde(%rip), %rsi      # 0x14610
movq %rax, %rdi
callq 0x31c0
leaq 0x4b30(%rip), %rsi      # 0x13171
movq %rax, %rdi
callq 0x31c0
movq %rax, %rdi
movl $0xc2, %esi
callq 0x3330
leaq 0x4b7c(%rip), %rsi      # 0x131d9
movq %rax, %rdi
callq 0x31c0
leaq 0x5ffa(%rip), %rsi      # 0x14666
jmp 0xe700
movq 0xa978(%rip), %rdi      # 0x18ff0
leaq 0x4b49(%rip), %rsi      # 0x131c8
callq 0x31c0
leaq 0x5f85(%rip), %rsi      # 0x14610
movq %rax, %rdi
callq 0x31c0
leaq 0x4ad7(%rip), %rsi      # 0x13171
movq %rax, %rdi
callq 0x31c0
movq %rax, %rdi
movl $0x9b, %esi
jmp 0xe6e5
movq 0xa93d(%rip), %rdi      # 0x18ff0
leaq 0x4b0e(%rip), %rsi      # 0x131c8
callq 0x31c0
leaq 0x5f4a(%rip), %rsi      # 0x14610
movq %rax, %rdi
callq 0x31c0
leaq 0x4a9c(%rip), %rsi      # 0x13171
movq %rax, %rdi
callq 0x31c0
movq %rax, %rdi
movl $0x6d, %esi
callq 0x3330
leaq 0x4ae8(%rip), %rsi      # 0x131d9
movq %rax, %rdi
callq 0x31c0
leaq 0x5f28(%rip), %rsi      # 0x14628
movq %rax, %rdi
callq 0x31c0
movq (%rbp), %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 0xe744
jmp 0xe739
jmp 0xe739
movq %rax, %rbx
movl $0x90, %esi
movq %r13, %rdi
callq 0x31f0
movq %rbx, %rdi
callq 0x3340
nop