// File: /workspace/github_cpp_makefile_star2_O2/dramninjasUMD[P]BOBSim/BOB.cpp
// Function: BOBSim::BOB::BOB()
BOB::BOB() : priorityPort(0),
	readCounter(0),
	writeCounter(0),
	committedWrites(0),
	clockCycleAdjustmentCounter(0),
	writeIssuedCB(NULL),
	rankBitWidth(log2(NUM_RANKS)),
	bankBitWidth(log2(NUM_BANKS)),
	rowBitWidth(log2(NUM_ROWS)),
	colBitWidth(log2(NUM_COLS)),
	busOffsetBitWidth(log2(BUS_ALIGNMENT_SIZE)),
	channelBitWidth(log2(NUM_CHANNELS)),
	cacheOffset(log2(CACHE_LINE_SIZE))
{
	/*
	  HACK!!! - QEMU does not support the huge memory sizes BOB can simulate.
	  Removing bits from the row address will have the least impact on function
	*/
	uint qemuMemoryBitWidth = log2_64(QEMU_MEMORY_SIZE);
	uint bitDifference = (busOffsetBitWidth + colBitWidth + rowBitWidth + channelBitWidth + rankBitWidth + bankBitWidth) - qemuMemoryBitWidth;
	rowBitWidth = rowBitWidth - bitDifference;
	//end hack


#ifdef LOG_OUTPUT
	string output_filename("BOBsim");
	if (getenv("SIM_DESC"))
		output_filename += getenv("SIM_DESC");
	output_filename += VARIANT_SUFFIX;
	output_filename += ".log";
	logOutput.open(output_filename.c_str());
#endif
	DEBUG("!!!!!!! QEMU_MEMORY_SIZE :"<<QEMU_MEMORY_SIZE<<" qemuMemoryBitWidth : "<<qemuMemoryBitWidth<<"   newRowBitWidth : "<<rowBitWidth<<"\n");
	DEBUG("busoff:"<<busOffsetBitWidth<<" col:"<<colBitWidth<<" row:"<<rowBitWidth<<" rank:"<<rankBitWidth<<" bank:"<<bankBitWidth<<" chan:"<<channelBitWidth);

	currentClockCycle = 0;

	//Compute ratios of various clock frequencies 
	if(fmod(CPU_CLK_PERIOD,LINK_BUS_CLK_PERIOD)>0.00001)
	{		
		ERROR("== ERROR - Link bus clock period ("<<LINK_BUS_CLK_PERIOD<<") must be a factor of CPU clock period ("<<CPU_CLK_PERIOD<<")");
		ERROR("==         fmod="<<fmod(CPU_CLK_PERIOD,LINK_BUS_CLK_PERIOD));
		abort(); 
	}

	LINK_CPU_CLK_RATIO = (CPU_CLK_PERIOD / LINK_BUS_CLK_PERIOD);
	cout<<"Channel to CPU ratio : "<<LINK_CPU_CLK_RATIO<<endl;
	DRAM_CPU_CLK_RATIO = tCK / CPU_CLK_PERIOD;
	cout<<"DRAM to CPU ratio : "<<DRAM_CPU_CLK_RATIO<<endl;
	DRAM_CPU_CLK_ADJUSTMENT = tCK / fmod(tCK,CPU_CLK_PERIOD);
	cout<<"DRAM_CPU_CLK_ADJUSTMENT : "<<DRAM_CPU_CLK_ADJUSTMENT<<endl;

	//Ensure that parameters have been set correclty
	if(NUM_CHANNELS / CHANNELS_PER_LINK_BUS != NUM_LINK_BUSES)
	{
		ERROR("== ERROR - Mismatch in NUM_CHANNELS and NUM_LINK_BUSES");
		exit(0);
	}

	if(DEBUG_BOB) DEBUG("== Channel-CPU clk ratio : "<<LINK_CPU_CLK_RATIO<<"  DRAM-CPU clk ratio : "<<DRAM_CPU_CLK_RATIO);

	//Make port objects
	for(unsigned i=0; i<NUM_PORTS; i++)
	{
		ports.push_back(Port(i));
	}

	//Initialize fields for bookkeeping
	inFlightRequestLinkCountdowns = vector<unsigned>(NUM_LINK_BUSES,0);
	inFlightResponseLinkCountdowns = vector<unsigned>(NUM_LINK_BUSES,0);

	inFlightRequestLink = vector<Transaction *> (NUM_LINK_BUSES, (Transaction*)(NULL));
	inFlightResponseLink = vector<Transaction *> (NUM_LINK_BUSES, (Transaction*)NULL);

	serDesBufferRequest = vector<Transaction *> (NUM_LINK_BUSES, (Transaction*)NULL);
	serDesBufferResponse = vector<Transaction *> (NUM_LINK_BUSES, (Transaction*)NULL);

	responseLinkRoundRobin = vector<unsigned> (NUM_LINK_BUSES,0);

	channelCounters = vector<unsigned>(NUM_CHANNELS,0);
	channelCountersLifetime = vector<uint64_t>(NUM_CHANNELS,0);

	portInputBufferAvg = vector<uint> (NUM_PORTS, 0);
	portOutputBufferAvg = vector<uint> (NUM_PORTS, 0);

	requestLinkIdle = vector<unsigned> (NUM_LINK_BUSES,0);
	responseLinkIdle = vector<unsigned> (NUM_LINK_BUSES,0);

	cmdQFull = vector<uint>(NUM_CHANNELS,0);

	//Define callback function
	Callback<BOB, void, BusPacket*, unsigned> *reportCallback = new Callback<BOB, void, BusPacket*, unsigned>(this, &BOB::ReportCallback);

	//Create channels
	channels.reserve(NUM_CHANNELS);
	for(unsigned i=0; i<NUM_CHANNELS; i++)
	{
		channels.push_back(new DRAMChannel(i,reportCallback));
	}

	//Used for round-robin
	priorityLinkBus = vector<unsigned>(NUM_PORTS,0);
}

// Assembly:
pushq %rbp
pushq %r15
pushq %r14
pushq %r13
pushq %r12
pushq %rbx
subq $0xd8, %rsp
movq %rdi, %r12
leaq 0x133c1(%rip), %rax     # 0x15b28
movq %rax, (%rdi)
leaq 0x10(%rdi), %r13
leaq 0x28(%rdi), %rax
movq %rax, 0x60(%rsp)
leaq 0x40(%rdi), %rax
movq %rax, 0x98(%rsp)
leaq 0x58(%rdi), %rax
movq %rax, 0x90(%rsp)
leaq 0x88(%rdi), %rax
movq %rax, 0x88(%rsp)
leaq 0xa0(%rdi), %rax
movq %rax, 0x80(%rsp)
leaq 0xb8(%rdi), %rax
movq %rax, 0xb0(%rsp)
leaq 0xd0(%rdi), %rax
movq %rax, 0xc0(%rsp)
leaq 0xe8(%rdi), %rax
movq %rax, 0xd0(%rsp)
leaq 0x100(%rdi), %rax
movq %rax, 0x78(%rsp)
leaq 0x118(%rdi), %rax
movq %rax, 0xa8(%rsp)
leaq 0x130(%rdi), %rax
movq %rax, 0xb8(%rsp)
leaq 0x148(%rdi), %rax
movq %rax, 0xc8(%rsp)
andq $0x0, 0x1d8(%rdi)
leaq 0x160(%rdi), %rax
movq %rax, 0x70(%rsp)
leaq 0x178(%rdi), %rax
movq %rax, 0xa0(%rsp)
leaq 0x198(%rdi), %rax
movq %rax, 0x8(%rsp)
leaq 0x1b0(%rdi), %rax
movq %rax, 0x68(%rsp)
movl $0x184, %edx            # imm = 0x184
movq %r13, %rdi
xorl %esi, %esi
callq 0x20d0
xorps %xmm0, %xmm0
movups %xmm0, 0x198(%r12)
movups %xmm0, 0x1a8(%r12)
movups %xmm0, 0x1b8(%r12)
movups %xmm0, 0x1c4(%r12)
pushq $0x4
popq %rdi
callq 0x5150
movl %eax, 0x1e0(%r12)
pushq $0x8
popq %rbx
movl %ebx, %edi
callq 0x5150
movl %eax, 0x1e4(%r12)
movl $0x10000, %edi          # imm = 0x10000
callq 0x5150
movl %eax, 0x1e8(%r12)
movl $0x800, %edi            # imm = 0x800
callq 0x5150
movl %eax, 0x1ec(%r12)
movl %ebx, %edi
callq 0x5150
movl %eax, 0x1f0(%r12)
movl %ebx, %edi
callq 0x5150
movl %eax, 0x1f4(%r12)
pushq $0x40
popq %rdi
callq 0x5150
movl %eax, 0x1f8(%r12)
andl $0x0, 0x1fc(%r12)
leaq 0x13988(%rip), %r14     # 0x16290
movq (%r14), %rdi
callq 0x516c
movl %eax, %r15d
movl 0x1f0(%r12), %eax
addl 0x1ec(%r12), %eax
addl 0x1f4(%r12), %eax
addl 0x1e0(%r12), %eax
addl 0x1e4(%r12), %eax
movl %r15d, %ecx
subl %eax, %ecx
movl %ecx, 0x1e8(%r12)
leaq 0x13865(%rip), %rbx     # 0x161b4
cmpl $0x0, (%rbx)
je 0x2a95
movq 0x13669(%rip), %rdi     # 0x15fc8
leaq 0xc7aa(%rip), %rsi      # 0xf110
callq 0x2180
movq (%r14), %rsi
movq %rax, %rdi
callq 0x2100
leaq 0xc7ae(%rip), %rsi      # 0xf12b
movq %rax, %rdi
callq 0x2180
movl %r15d, %esi
movq %rax, %rdi
callq 0x2100
leaq 0xc7ab(%rip), %rsi      # 0xf142
movq %rax, %rdi
callq 0x2180
movl 0x1e8(%r12), %esi
movq %rax, %rdi
callq 0x2100
leaq 0xcc31(%rip), %rsi      # 0xf5e7
movq %rax, %rdi
callq 0x2180
movq %rax, %rdi
callq 0x20b0
cmpl $0x0, (%rbx)
je 0x2a95
movq 0x135f2(%rip), %rdi     # 0x15fc8
leaq 0xc77a(%rip), %rsi      # 0xf157
callq 0x2180
movl 0x1f0(%r12), %esi
movq %rax, %rdi
callq 0x2100
leaq 0xc766(%rip), %rsi      # 0xf15f
movq %rax, %rdi
callq 0x2180
movl 0x1ec(%r12), %esi
movq %rax, %rdi
callq 0x2100
leaq 0xc74d(%rip), %rsi      # 0xf165
movq %rax, %rdi
callq 0x2180
movl 0x1e8(%r12), %esi
movq %rax, %rdi
callq 0x2100
leaq 0xc734(%rip), %rsi      # 0xf16b
movq %rax, %rdi
callq 0x2180
movl 0x1e0(%r12), %esi
movq %rax, %rdi
callq 0x2100
leaq 0xc71c(%rip), %rsi      # 0xf172
movq %rax, %rdi
callq 0x2180
movl 0x1e4(%r12), %esi
movq %rax, %rdi
callq 0x2100
leaq 0xc704(%rip), %rsi      # 0xf179
movq %rax, %rdi
callq 0x2180
movl 0x1f4(%r12), %esi
movq %rax, %rdi
callq 0x2100
movq %rax, %rdi
callq 0x20b0
andq $0x0, 0x8(%r12)
movl $0x1, 0x137d3(%rip)     # 0x16278
movq 0x1351c(%rip), %rdi     # 0x15fc8
leaq 0xc6e3(%rip), %rsi      # 0xf196
callq 0x2180
movl 0x137ba(%rip), %esi     # 0x16278
movq %rax, %rdi
callq 0x2100
movq %rax, %rdi
callq 0x20b0
movl $0x4, 0x137a4(%rip)     # 0x1627c
movq 0x134e9(%rip), %rdi     # 0x15fc8
leaq 0xc6c8(%rip), %rsi      # 0xf1ae
callq 0x2180
movl 0x1378b(%rip), %esi     # 0x1627c
movq %rax, %rdi
callq 0x2100
movq %rax, %rdi
callq 0x20b0
movl $0x6, 0x13775(%rip)     # 0x16280
movq 0x134b6(%rip), %rdi     # 0x15fc8
leaq 0xc6aa(%rip), %rsi      # 0xf1c3
callq 0x2180
movl 0x1375c(%rip), %esi     # 0x16280
movq %rax, %rdi
callq 0x2100
movq %rax, %rdi
callq 0x20b0
xorl %ebp, %ebp
leaq 0x13673(%rip), %r14     # 0x161b0
leaq 0x20(%rsp), %r15
cmpl (%r14), %ebp
jae 0x2b68
movq %r15, %rdi
movl %ebp, %esi
callq 0xba1c
movq %r13, %rdi
movq %r15, %rsi
callq 0x5538
movq %r15, %rdi
callq 0x5190
incl %ebp
jmp 0x2b42
leaq 0x10(%rsp), %rdx
andl $0x0, (%rdx)
leaq 0x20(%rsp), %rdi
pushq $0x4
popq %rsi
leaq 0x7(%rsp), %rcx
callq 0x51aa
leaq 0x20(%rsp), %rbx
movq 0xd0(%rsp), %rdi
movq %rbx, %rsi
callq 0x57f6
movq %rbx, %rdi
callq 0x549c
leaq 0x10(%rsp), %rdx
andl $0x0, (%rdx)
leaq 0x20(%rsp), %rdi
pushq $0x4
popq %rsi
leaq 0x7(%rsp), %rcx
callq 0x51aa
leaq 0x20(%rsp), %rbx
movq 0xc8(%rsp), %rdi
movq %rbx, %rsi
callq 0x57f6
movq %rbx, %rdi
callq 0x549c
leaq 0x10(%rsp), %rdx
andq $0x0, (%rdx)
leaq 0x20(%rsp), %rdi
pushq $0x4
popq %rsi
leaq 0x7(%rsp), %rcx
callq 0x5200
leaq 0x20(%rsp), %rbx
movq 0xc0(%rsp), %rdi
movq %rbx, %rsi
callq 0x58fe
movq %rbx, %rdi
callq 0x5504
leaq 0x10(%rsp), %rdx
andq $0x0, (%rdx)
leaq 0x20(%rsp), %rdi
pushq $0x4
popq %rsi
leaq 0x7(%rsp), %rcx
callq 0x5200
leaq 0x20(%rsp), %rbx
movq 0xb8(%rsp), %rdi
movq %rbx, %rsi
callq 0x58fe
movq %rbx, %rdi
callq 0x5504
leaq 0x10(%rsp), %rdx
andq $0x0, (%rdx)
leaq 0x20(%rsp), %rdi
pushq $0x4
popq %rsi
leaq 0x7(%rsp), %rcx
callq 0x5200
leaq 0x20(%rsp), %rbx
movq 0xb0(%rsp), %rdi
movq %rbx, %rsi
callq 0x58fe
movq %rbx, %rdi
callq 0x5504
leaq 0x10(%rsp), %rdx
andq $0x0, (%rdx)
leaq 0x20(%rsp), %rdi
pushq $0x4
popq %rsi
leaq 0x7(%rsp), %rcx
callq 0x5200
leaq 0x20(%rsp), %rbx
movq 0xa8(%rsp), %rdi
movq %rbx, %rsi
callq 0x58fe
movq %rbx, %rdi
callq 0x5504
leaq 0x10(%rsp), %rdx
andl $0x0, (%rdx)
leaq 0x20(%rsp), %rdi
pushq $0x4
popq %rsi
leaq 0x7(%rsp), %rcx
callq 0x51aa
leaq 0x20(%rsp), %rbx
movq 0xa0(%rsp), %rdi
movq %rbx, %rsi
callq 0x57f6
movq %rbx, %rdi
callq 0x549c
leaq 0x10(%rsp), %rdx
andl $0x0, (%rdx)
leaq 0x20(%rsp), %rdi
pushq $0x8
popq %rsi
leaq 0x7(%rsp), %rcx
callq 0x51aa
leaq 0x20(%rsp), %rbx
movq 0x98(%rsp), %rdi
movq %rbx, %rsi
callq 0x57f6
movq %rbx, %rdi
callq 0x549c
leaq 0x10(%rsp), %rdx
andq $0x0, (%rdx)
leaq 0x20(%rsp), %rdi
pushq $0x8
popq %rsi
leaq 0x7(%rsp), %rcx
callq 0x5256
leaq 0x20(%rsp), %rbx
movq 0x90(%rsp), %rdi
movq %rbx, %rsi
callq 0x5a06
movq %rbx, %rdi
callq 0x54d0
movl (%r14), %esi
leaq 0x10(%rsp), %rdx
andl $0x0, (%rdx)
leaq 0x20(%rsp), %rdi
leaq 0x7(%rsp), %rcx
callq 0x51aa
leaq 0x20(%rsp), %rbx
movq 0x88(%rsp), %rdi
movq %rbx, %rsi
callq 0x57f6
movq %rbx, %rdi
callq 0x549c
movl (%r14), %esi
leaq 0x10(%rsp), %rdx
andl $0x0, (%rdx)
leaq 0x20(%rsp), %rdi
leaq 0x7(%rsp), %rcx
callq 0x51aa
leaq 0x20(%rsp), %rbx
movq 0x80(%rsp), %rdi
movq %rbx, %rsi
callq 0x57f6
movq %rbx, %rdi
callq 0x549c
leaq 0x10(%rsp), %rdx
andl $0x0, (%rdx)
leaq 0x20(%rsp), %rdi
pushq $0x4
popq %rsi
leaq 0x7(%rsp), %rcx
callq 0x51aa
leaq 0x20(%rsp), %rbx
movq 0x78(%rsp), %rdi
movq %rbx, %rsi
callq 0x57f6
movq %rbx, %rdi
callq 0x549c
leaq 0x10(%rsp), %rdx
andl $0x0, (%rdx)
leaq 0x20(%rsp), %rdi
pushq $0x4
popq %rsi
leaq 0x7(%rsp), %rcx
callq 0x51aa
leaq 0x20(%rsp), %rbx
movq 0x70(%rsp), %rdi
movq %rbx, %rsi
callq 0x57f6
movq %rbx, %rdi
callq 0x549c
leaq 0x10(%rsp), %rdx
andl $0x0, (%rdx)
leaq 0x20(%rsp), %rdi
pushq $0x8
popq %rsi
leaq 0x7(%rsp), %rcx
callq 0x51aa
movq %r13, 0x18(%rsp)
leaq 0x20(%rsp), %rbx
movq 0x68(%rsp), %rdi
movq %rbx, %rsi
callq 0x57f6
movq %rbx, %rdi
callq 0x549c
pushq $0x20
popq %rdi
callq 0x2190
movq %rax, %r15
leaq 0x12ceb(%rip), %rax     # 0x15b68
movq %rax, (%r15)
movq %r12, 0x8(%r15)
leaq 0x1cd(%rip), %rax       # 0x3058
movq %rax, 0x10(%r15)
andq $0x0, 0x18(%r15)
pushq $0x8
popq %rsi
movq 0x60(%rsp), %rdi
callq 0x52ac
xorl %r13d, %r13d
leaq 0x20(%rsp), %rbp
cmpl $0x8, %r13d
je 0x2ee1
movl $0x280, %edi            # imm = 0x280
callq 0x2190
movq %rax, %rbx
movq %rax, %rdi
movl %r13d, %esi
movq %r15, %rdx
callq 0x9b50
movq %rbx, 0x20(%rsp)
movq 0x60(%rsp), %rdi
movq %rbp, %rsi
callq 0x5abc
incl %r13d
jmp 0x2ea9
movl (%r14), %esi
leaq 0x10(%rsp), %rdx
andl $0x0, (%rdx)
leaq 0x20(%rsp), %rdi
leaq 0x7(%rsp), %rcx
callq 0x51aa
leaq 0x20(%rsp), %rbx
movq 0x8(%rsp), %rdi
movq %rbx, %rsi
callq 0x57f6
movq %rbx, %rdi
callq 0x549c
addq $0xd8, %rsp
popq %rbx
popq %r12
popq %r13
popq %r14
popq %r15
popq %rbp
retq
jmp 0x2f6f
jmp 0x2f6a
jmp 0x2f6a
jmp 0x2f6a
jmp 0x2f6a
jmp 0x2f6a
jmp 0x2f6a
jmp 0x2f6a
jmp 0x2f6a
jmp 0x2f6a
jmp 0x2f6a
jmp 0x2f6a
jmp 0x2f6a
jmp 0x2f6a
jmp 0x2f6a
jmp 0x2f6f
jmp 0x2f6a
movq %rax, %r14
movl $0x280, %esi            # imm = 0x280
movq %rbx, %rdi
callq 0x21b0
jmp 0x2f72
movq %rax, %r14
leaq 0x20(%rsp), %rdi
callq 0x5190
jmp 0x2f77
movq %rax, %r14
jmp 0x2f77
movq %rax, %r14
movq 0x18(%rsp), %r13
movq 0x8(%rsp), %rbx
addq $0x70, %r12
movq 0x68(%rsp), %rdi
callq 0x549c
movq %rbx, %rdi
callq 0x549c
movq 0xa0(%rsp), %rdi
callq 0x549c
movq 0x70(%rsp), %rdi
callq 0x549c
movq 0xc8(%rsp), %rdi
callq 0x549c
movq 0xb8(%rsp), %rdi
callq 0x5504
movq 0xa8(%rsp), %rdi
callq 0x5504
movq 0x78(%rsp), %rdi
callq 0x549c
movq 0xd0(%rsp), %rdi
callq 0x549c
movq 0xc0(%rsp), %rdi
callq 0x5504
movq 0xb0(%rsp), %rdi
callq 0x5504
movq 0x80(%rsp), %rdi
callq 0x549c
movq 0x88(%rsp), %rdi
callq 0x549c
movq %r12, %rdi
callq 0x5504
movq 0x90(%rsp), %rdi
callq 0x54d0
movq 0x98(%rsp), %rdi
callq 0x549c
movq 0x60(%rsp), %rdi
callq 0x5468
movq %r13, %rdi
callq 0x5342
movq %r14, %rdi
callq 0x22f0
nop