// File: /workspace/github_cpp_makefile_star2_O2/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 $0x28, %rsp
movq %rdi, %rbx
leaq 0x90(%rdi), %r14
movq 0x90(%rdi), %rax
cmpq %rax, 0x98(%rdi)
je 0xadb0
movq (%rbx), %rdi
movq (%rax), %rsi
movq (%rdi), %rax
xorl %edx, %edx
callq *0x10(%rax)
testb %al, %al
je 0xadb0
movq (%r14), %rsi
movq (%rsi), %rax
cmpl $0x4, (%rax)
jne 0xada8
xorps %xmm0, %xmm0
movups %xmm0, 0x18(%rbx)
movq %r14, %rdi
callq 0x53ca
leaq 0x18(%rbx), %rax
movq %rax, 0x8(%rsp)
movq %rbx, 0x20(%rsp)
cmpq $0x0, 0x18(%rbx)
movq %r14, 0x10(%rsp)
je 0xaeb3
movq 0x20(%rsp), %r13
movq 0x78(%r13), %rsi
cmpq 0x80(%r13), %rsi
je 0xafea
movq (%rsi), %r14
cmpl $0x2, (%r14)
jne 0xafea
movq 0x8(%rsp), %rax
movq (%rax), %rbx
testq %rbx, %rbx
je 0xb135
leaq 0x78(%r13), %r12
movq 0x20(%r13), %r15
movl (%r15), %eax
cmpl $0x2, %eax
je 0xafa0
cmpl $0x1, %eax
jne 0xb1f8
movl $0x90, %edi
callq 0x2190
movq 0x8(%r14), %rcx
subq 0x8(%rbx), %rcx
movq %rax, %r14
movq 0x8(%r15), %rax
addq (%rax), %rcx
pushq $0x1
popq %rsi
pushq $0x40
popq %rdx
movq %r14, %rdi
callq 0xe6e0
leaq 0x18(%rsp), %rsi
movq %r14, (%rsi)
movb $0x1, 0x30(%r14)
movq 0x10(%rsp), %rbx
movq %rbx, %rdi
callq 0x53ac
incl 0xa8(%r13)
movq 0x78(%r13), %rsi
movq %r12, %rdi
callq 0x53ca
movl 0xa8(%r13), %eax
movq 0x20(%r13), %rcx
movq 0x8(%rcx), %rcx
cmpq %rax, 0x8(%rcx)
jne 0xafea
movq 0x18(%r13), %rax
movl $0x4, (%rax)
movq %rbx, %rdi
movq 0x8(%rsp), %rsi
callq 0x53ac
andl $0x0, 0xa8(%r13)
jmp 0xafea
movq 0x20(%rsp), %rcx
movq 0x58(%rcx), %rax
cmpq 0x38(%rcx), %rax
je 0xadce
movq 0x20(%rsp), %rbx
leaq 0x38(%rbx), %r14
movq %r14, %rdi
xorl %esi, %esi
callq 0xb7f4
movq (%rax), %rax
cmpq $0x0, 0x28(%rax)
je 0xb196
leaq 0x28(%rbx), %r12
movq %r14, %rdi
xorl %esi, %esi
callq 0xb7f4
movq (%rax), %rax
movq 0x28(%rax), %rax
movq %rax, 0x20(%rbx)
movq %r14, %rdi
xorl %esi, %esi
callq 0xb7f4
movq (%rax), %rax
movq %rax, 0x18(%rbx)
movq %r12, %rdi
callq 0xb3ec
movq 0x20(%rbx), %r15
movl (%r15), %eax
testl %eax, %eax
je 0xb089
cmpl $0x1, %eax
je 0xaffd
cmpl $0x2, %eax
jne 0xb269
xorl %ebx, %ebx
pushq $0x40
popq %rbp
leaq 0x18(%rsp), %r14
movq 0x10(%r15), %rax
subq 0x8(%r15), %rax
sarq $0x3, %rax
cmpq %rax, %rbx
jae 0xadce
movl $0x90, %edi
callq 0x2190
movq %rax, %r12
movq 0x8(%r15), %rax
movq (%rax,%rbx,8), %rcx
movq %r12, %rdi
xorl %esi, %esi
movl %ebp, %edx
callq 0xe6e0
movq %r12, 0x18(%rsp)
movb $0x1, 0x30(%r12)
movq 0x10(%rsp), %rdi
movq %r14, %rsi
callq 0x53ac
incq %rbx
movq 0x20(%rsp), %rax
movq 0x20(%rax), %r15
jmp 0xaf44
movl 0xa8(%r13), %eax
incl %eax
movl %eax, 0xa8(%r13)
movq 0x10(%r15), %rcx
subq 0x8(%r15), %rcx
sarq $0x3, %rcx
cmpq %rax, %rcx
jne 0xafe2
movl $0x4, (%rbx)
movq 0x10(%rsp), %rdi
movq 0x8(%rsp), %rsi
callq 0x53ac
andl $0x0, 0xa8(%r13)
movq 0x78(%r13), %rsi
movq %r12, %rdi
callq 0x53ca
incq 0x10(%r13)
addq $0x28, %rsp
popq %rbx
popq %r12
popq %r13
popq %r14
popq %r15
popq %rbp
retq
movq 0x8(%r15), %rax
movq 0x10(%r15), %rcx
subq %rax, %rcx
cmpq $0x10, %rcx
jne 0xb2c2
movq 0x8(%rsp), %rcx
movq (%rcx), %rcx
movq 0x8(%rcx), %r15
movq 0x8(%rax), %r13
xorl %ebx, %ebx
pushq $0x8
popq %rbp
cmpq %rbx, %r13
je 0xadce
movl $0x90, %edi
callq 0x2190
movq %rax, %r14
movl %ebp, %edi
callq 0x5150
movl %eax, %r12d
movl %ebp, %edi
callq 0x5150
addl %eax, %r12d
movl %ebx, %eax
movl %r12d, %ecx
shll %cl, %eax
movslq %eax, %rcx
addq %r15, %rcx
movq %r14, %rdi
xorl %esi, %esi
pushq $0x40
popq %rdx
callq 0xe6e0
movq %r14, 0x18(%rsp)
movb $0x1, 0x30(%r14)
movq 0x10(%rsp), %rdi
leaq 0x18(%rsp), %rsi
callq 0x53ac
incq %rbx
jmp 0xb027
movq 0x8(%r15), %rax
movq 0x10(%r15), %rcx
subq %rax, %rcx
cmpq $0x10, %rcx
movq 0x10(%rsp), %r12
jne 0xb329
movq 0x8(%rsp), %rcx
movq (%rcx), %rcx
movq 0x8(%rcx), %r14
movq (%rax), %r15
xorl %ebx, %ebx
pushq $0x8
popq %rbp
cmpq %rbx, %r15
je 0xb11a
movl $0x90, %edi
callq 0x2190
movq %rax, %r12
movl %ebp, %edi
callq 0x5150
movl %eax, %r13d
movl %ebp, %edi
callq 0x5150
addl %eax, %r13d
movl %ebx, %eax
movl %r13d, %ecx
shll %cl, %eax
movslq %eax, %rcx
addq %r14, %rcx
movq %r12, %rdi
pushq $0x1
popq %rsi
pushq $0x40
popq %rdx
callq 0xe6e0
movq %r12, 0x18(%rsp)
movb $0x1, 0x30(%r12)
movq 0x10(%rsp), %r12
movq %r12, %rdi
leaq 0x18(%rsp), %rsi
callq 0x53ac
incq %rbx
jmp 0xb0b7
movq 0x8(%rsp), %rsi
movq (%rsi), %rax
movl $0x4, (%rax)
movq %r12, %rdi
callq 0x53ac
jmp 0xadce
movq 0xaeb4(%rip), %rdi      # 0x15ff0
leaq 0x403d(%rip), %rsi      # 0xf180
callq 0x2180
leaq 0x5431(%rip), %rsi      # 0x10580
movq %rax, %rdi
callq 0x2180
leaq 0x3fcb(%rip), %rsi      # 0xf129
movq %rax, %rdi
callq 0x2180
movq %rax, %rdi
movl $0xd7, %esi
callq 0x22e0
leaq 0x4017(%rip), %rsi      # 0xf191
movq %rax, %rdi
callq 0x2180
leaq 0x54ac(%rip), %rsi      # 0x10635
movq %rax, %rdi
callq 0x2180
jmp 0xb391
movq 0xae53(%rip), %rdi      # 0x15ff0
leaq 0x3fdc(%rip), %rsi      # 0xf180
callq 0x2180
leaq 0x53d0(%rip), %rsi      # 0x10580
movq %rax, %rdi
callq 0x2180
leaq 0x3f6a(%rip), %rsi      # 0xf129
movq %rax, %rdi
callq 0x2180
movq %rax, %rdi
movl $0xc9, %esi
callq 0x22e0
leaq 0x3fb6(%rip), %rsi      # 0xf191
movq %rax, %rdi
callq 0x2180
leaq 0x541c(%rip), %rsi      # 0x10606
movq %rax, %rdi
callq 0x2180
movq 0x78(%rbx), %rcx
jmp 0xb259
movq 0xadf1(%rip), %rdi      # 0x15ff0
leaq 0x3f7a(%rip), %rsi      # 0xf180
callq 0x2180
leaq 0x536e(%rip), %rsi      # 0x10580
movq %rax, %rdi
callq 0x2180
leaq 0x3f08(%rip), %rsi      # 0xf129
movq %rax, %rdi
callq 0x2180
movq %rax, %rdi
movl $0x10c, %esi            # imm = 0x10C
callq 0x22e0
leaq 0x3f54(%rip), %rsi      # 0xf191
movq %rax, %rdi
callq 0x2180
leaq 0x5425(%rip), %rsi      # 0x10671
movq %rax, %rdi
callq 0x2180
movq 0x8(%rsp), %rcx
movq (%rcx), %rsi
movq %rax, %rdi
callq 0xe728
jmp 0xb391
movq 0xad80(%rip), %rdi      # 0x15ff0
leaq 0x3f09(%rip), %rsi      # 0xf180
callq 0x2180
leaq 0x52fd(%rip), %rsi      # 0x10580
movq %rax, %rdi
callq 0x2180
leaq 0x3e97(%rip), %rsi      # 0xf129
movq %rax, %rdi
callq 0x2180
movq %rax, %rdi
movl $0xc2, %esi
callq 0x22e0
leaq 0x3ee3(%rip), %rsi      # 0xf191
movq %rax, %rdi
callq 0x2180
leaq 0x5319(%rip), %rsi      # 0x105d6
jmp 0xb37b
movq 0xad27(%rip), %rdi      # 0x15ff0
leaq 0x3eb0(%rip), %rsi      # 0xf180
callq 0x2180
leaq 0x52a4(%rip), %rsi      # 0x10580
movq %rax, %rdi
callq 0x2180
leaq 0x3e3e(%rip), %rsi      # 0xf129
movq %rax, %rdi
callq 0x2180
movq %rax, %rdi
movl $0x9b, %esi
callq 0x22e0
leaq 0x3e8a(%rip), %rsi      # 0xf191
movq %rax, %rdi
callq 0x2180
leaq 0x5282(%rip), %rsi      # 0x10598
movq %rax, %rdi
callq 0x2180
movq 0x20(%rsp), %rcx
movq 0x20(%rcx), %rcx
jmp 0xb387
movq 0xacc0(%rip), %rdi      # 0x15ff0
leaq 0x3e49(%rip), %rsi      # 0xf180
callq 0x2180
leaq 0x523d(%rip), %rsi      # 0x10580
movq %rax, %rdi
callq 0x2180
leaq 0x3dd7(%rip), %rsi      # 0xf129
movq %rax, %rdi
callq 0x2180
pushq $0x6d
popq %rsi
movq %rax, %rdi
callq 0x22e0
leaq 0x3e25(%rip), %rsi      # 0xf191
movq %rax, %rdi
callq 0x2180
leaq 0x521d(%rip), %rsi      # 0x10598
movq %rax, %rdi
callq 0x2180
movq 0x20(%rbx), %rcx
movl (%rcx), %esi
movq %rax, %rdi
callq 0x22e0
movq %rax, %rdi
callq 0x20b0
pushq $-0x1
popq %rdi
callq 0x21d0
jmp 0xb3a5
jmp 0xb3b2
movq %rax, %rbx
movl $0x90, %esi
movq %r14, %rdi
jmp 0xb3bd
movq %rax, %rbx
movl $0x90, %esi
movq %r12, %rdi
callq 0x21b0
movq %rbx, %rdi
callq 0x22f0