// File: CMU-SAFARI[P]SMLA/src/Controller.h
// Function: ramulator::Controller<ramulator::WideIO>::tick()
void tick()
    {
        clk++;

				if (channel->spec->standard_name.substr(0,8) == "SMLA_CIO"
							&& channel->id % 4 != clk % 4)  {
					return;
				}

        req_queue_length_sum += readq.size() + writeq.size() + pending.size();
        read_req_queue_length_sum += readq.size() + pending.size();
        write_req_queue_length_sum += writeq.size();

        /*** 1. Serve completed reads ***/
        if (pending.size()) {
            Request& req = pending[0];
            if (req.depart <= clk) {
                if (req.depart - req.arrive > 1) { // this request really accessed a row
                  read_latency_sum += req.depart - req.arrive;
                  channel->update_serving_requests(
                      req.addr_vec.data(), -1, clk);
                }
                req.callback(req);
                pending.pop_front();
            }
        }

        /*** 2. Refresh scheduler ***/
        refresh->tick_ref();

        /*** 3. Should we schedule writes? ***/
        if (!write_mode) {
            // yes -- write queue is almost full or read queue is empty
            if (writeq.size() >= int(0.8 * writeq.max) || readq.size() == 0)
                write_mode = true;
        }
        else {
            // no -- write queue is almost empty and read queue is not empty
            if (writeq.size() <= int(0.2 * writeq.max) && readq.size() != 0)
                write_mode = false;
        }

        /*** 4. Find the best command to schedule, if any ***/
        Queue* queue = !write_mode ? &readq : &writeq;
        if (otherq.size())
            queue = &otherq;  // "other" requests are rare, so we give them precedence over reads/writes

        auto req = scheduler->get_head(queue->q);
        if (req == queue->q.end() || !is_ready(req)) {
            // we couldn't find a command to schedule -- let's try to be speculative
            auto cmd = T::Command::PRE;
            vector<int> victim = rowpolicy->get_victim(cmd);
            if (!victim.empty()){
                issue_cmd(cmd, victim);
            }
            return;  // nothing more to be done this cycle
        }

        if (req->is_first_command) {
            req->is_first_command = false;
            int coreid = req->coreid;
            if (req->type == Request::Type::READ || req->type == Request::Type::WRITE) {
              channel->update_serving_requests(req->addr_vec.data(), 1, clk);
            }
            int tx = (channel->spec->prefetch_size * channel->spec->channel_width / 8);
            if (req->type == Request::Type::READ) {
                if (is_row_hit(req)) {
                    ++read_row_hits[coreid];
                    ++row_hits;
                } else if (is_row_open(req)) {
                    ++read_row_conflicts[coreid];
                    ++row_conflicts;
                } else {
                    ++read_row_misses[coreid];
                    ++row_misses;
                }
              read_transaction_bytes += tx;
            } else if (req->type == Request::Type::WRITE) {
              if (is_row_hit(req)) {
                  ++write_row_hits[coreid];
                  ++row_hits;
              } else if (is_row_open(req)) {
                  ++write_row_conflicts[coreid];
                  ++row_conflicts;
              } else {
                  ++write_row_misses[coreid];
                  ++row_misses;
              }
              write_transaction_bytes += tx;
            }
        }

        // issue command on behalf of request
        auto cmd = get_first_cmd(req);
        issue_cmd(cmd, get_addr_vec(cmd, req));

        // check whether this is the last command (which finishes the request)
        if (cmd != channel->spec->translate[int(req->type)])
            return;

        // set a future completion time for read requests
        if (req->type == Request::Type::READ) {
            req->depart = clk + channel->spec->read_latency_smla[channel->id % 4];
            pending.push_back(*req);
        }

        if (req->type == Request::Type::WRITE) {
            channel->update_serving_requests(req->addr_vec.data(), -1, clk);
        }

        // remove request from queue
        queue->q.erase(req);
    }

// Assembly:
pushq %rbp
movq %rsp, %rbp
subq $0x1a0, %rsp            # imm = 0x1A0
movq %rdi, -0x8(%rbp)
movq -0x8(%rbp), %rax
movq %rax, -0x118(%rbp)
movq 0xff8(%rax), %rcx
addq $0x1, %rcx
movq %rcx, 0xff8(%rax)
leaq -0x28(%rbp), %rdi
leaq 0xba489(%rip), %rsi     # 0xe36a0
xorl %eax, %eax
movl %eax, %edx
movl $0x8, %ecx
callq 0x6370
leaq -0x28(%rbp), %rdi
leaq 0x71177(%rip), %rsi     # 0x9a3a7
callq 0x8c30
movb %al, %cl
xorl %eax, %eax
testb $0x1, %cl
movb %al, -0x109(%rbp)
jne 0x29246
jmp 0x29297
movq -0x118(%rbp), %rax
movq 0x1000(%rax), %rax
movl 0x39c(%rax), %eax
movl $0x4, %ecx
cltd
idivl %ecx
movq -0x118(%rbp), %rax
movslq %edx, %rcx
movq %rcx, -0x120(%rbp)
movq 0xff8(%rax), %rax
movl $0x4, %ecx
cqto
idivq %rcx
movq -0x120(%rbp), %rax
cmpq %rdx, %rax
setne %al
movb %al, -0x109(%rbp)
movb -0x109(%rbp), %al
movb %al, -0x121(%rbp)
leaq -0x28(%rbp), %rdi
callq 0x6668
movb -0x121(%rbp), %al
testb $0x1, %al
jne 0x292b8
jmp 0x292bd
jmp 0x29c43
movq -0x118(%rbp), %rdi
addq $0x1028, %rdi           # imm = 0x1028
callq 0x29110
movq -0x118(%rbp), %rdi
movl %eax, -0x13c(%rbp)
addq $0x1048, %rdi           # imm = 0x1048
callq 0x29110
movq -0x118(%rbp), %rdi
movl %eax, %ecx
movl -0x13c(%rbp), %eax
addl %ecx, %eax
movl %eax, %eax
movq %rax, -0x138(%rbp)
addq $0x1088, %rdi           # imm = 0x1088
callq 0x29130
movq -0x118(%rbp), %rdi
movq %rax, %rcx
movq -0x138(%rbp), %rax
addq %rcx, %rax
movq %rax, -0x30(%rbp)
addq $0x8e0, %rdi            # imm = 0x8E0
leaq -0x30(%rbp), %rsi
callq 0x29de0
movq -0x118(%rbp), %rdi
addq $0x1028, %rdi           # imm = 0x1028
callq 0x29110
movq -0x118(%rbp), %rdi
movl %eax, %eax
movq %rax, -0x130(%rbp)
addq $0x1088, %rdi           # imm = 0x1088
callq 0x29130
movq -0x118(%rbp), %rdi
movq %rax, %rcx
movq -0x130(%rbp), %rax
addq %rcx, %rax
movq %rax, -0x38(%rbp)
addq $0xa10, %rdi            # imm = 0xA10
leaq -0x38(%rbp), %rsi
callq 0x29de0
movq -0x118(%rbp), %rdi
addq $0x1048, %rdi           # imm = 0x1048
callq 0x29110
movq -0x118(%rbp), %rdi
movl %eax, -0x3c(%rbp)
addq $0xb40, %rdi            # imm = 0xB40
leaq -0x3c(%rbp), %rsi
callq 0x29e10
movq -0x118(%rbp), %rdi
addq $0x1088, %rdi           # imm = 0x1088
callq 0x29130
cmpq $0x0, %rax
je 0x294ba
movq -0x118(%rbp), %rdi
addq $0x1088, %rdi           # imm = 0x1088
xorl %eax, %eax
movl %eax, %esi
callq 0x29e40
movq -0x118(%rbp), %rcx
movq %rax, -0x48(%rbp)
movq -0x48(%rbp), %rax
movq 0x38(%rax), %rax
cmpq 0xff8(%rcx), %rax
jg 0x294b8
movq -0x48(%rbp), %rax
movq 0x38(%rax), %rax
movq -0x48(%rbp), %rcx
subq 0x30(%rcx), %rax
cmpq $0x1, %rax
jle 0x29494
movq -0x118(%rbp), %rdi
movq -0x48(%rbp), %rax
movq 0x38(%rax), %rax
movq -0x48(%rbp), %rcx
subq 0x30(%rcx), %rax
movq %rax, -0x50(%rbp)
addq $0x7b0, %rdi            # imm = 0x7B0
leaq -0x50(%rbp), %rsi
callq 0x29e70
movq -0x118(%rbp), %rax
movq 0x1000(%rax), %rax
movq %rax, -0x148(%rbp)
movq -0x48(%rbp), %rdi
addq $0x10, %rdi
callq 0x1c170
movq -0x148(%rbp), %rdi
movq %rax, %rsi
movq -0x118(%rbp), %rax
movq 0xff8(%rax), %rcx
movl $0xffffffff, %edx       # imm = 0xFFFFFFFF
callq 0x29ea0
movq -0x48(%rbp), %rdi
addq $0x40, %rdi
movq -0x48(%rbp), %rsi
callq 0x2a1f0
movq -0x118(%rbp), %rdi
addq $0x1088, %rdi           # imm = 0x1088
callq 0x2a230
jmp 0x294ba
movq -0x118(%rbp), %rax
movq 0x1020(%rax), %rdi
callq 0x2a2a0
movq -0x118(%rbp), %rax
testb $0x1, 0x10d8(%rax)
jne 0x2953e
movq -0x118(%rbp), %rdi
addq $0x1048, %rdi           # imm = 0x1048
callq 0x29110
movq -0x118(%rbp), %rcx
movl 0x1060(%rcx), %ecx
cvtsi2sd %rcx, %xmm1
movsd 0x70b16(%rip), %xmm0    # 0x9a020
mulsd %xmm1, %xmm0
cvttsd2si %xmm0, %ecx
cmpl %ecx, %eax
jae 0x2952e
movq -0x118(%rbp), %rdi
addq $0x1028, %rdi           # imm = 0x1028
callq 0x29110
cmpl $0x0, %eax
jne 0x2953c
movq -0x118(%rbp), %rax
movb $0x1, 0x10d8(%rax)
jmp 0x2959f
movq -0x118(%rbp), %rdi
addq $0x1048, %rdi           # imm = 0x1048
callq 0x29110
movq -0x118(%rbp), %rcx
movl 0x1060(%rcx), %ecx
cvtsi2sd %rcx, %xmm1
movsd 0x70abd(%rip), %xmm0    # 0x9a028
mulsd %xmm1, %xmm0
cvttsd2si %xmm0, %ecx
cmpl %ecx, %eax
ja 0x2959d
movq -0x118(%rbp), %rdi
addq $0x1028, %rdi           # imm = 0x1028
callq 0x29110
cmpl $0x0, %eax
je 0x2959d
movq -0x118(%rbp), %rax
movb $0x0, 0x10d8(%rax)
jmp 0x2959f
movq -0x118(%rbp), %rax
testb $0x1, 0x10d8(%rax)
jne 0x295c5
movq -0x118(%rbp), %rax
addq $0x1028, %rax           # imm = 0x1028
movq %rax, -0x150(%rbp)
jmp 0x295d9
movq -0x118(%rbp), %rax
addq $0x1048, %rax           # imm = 0x1048
movq %rax, -0x150(%rbp)
movq -0x118(%rbp), %rdi
movq -0x150(%rbp), %rax
movq %rax, -0x58(%rbp)
addq $0x1068, %rdi           # imm = 0x1068
callq 0x29110
cmpl $0x0, %eax
je 0x2960d
movq -0x118(%rbp), %rax
addq $0x1068, %rax           # imm = 0x1068
movq %rax, -0x58(%rbp)
movq -0x118(%rbp), %rax
movq 0x1008(%rax), %rdi
movq -0x58(%rbp), %rsi
callq 0x2a300
movq %rax, -0x60(%rbp)
movq -0x58(%rbp), %rdi
callq 0x2aa90
movq %rax, -0x68(%rbp)
leaq -0x60(%rbp), %rdi
leaq -0x68(%rbp), %rsi
callq 0x2aa60
movb %al, %cl
movb $0x1, %al
testb $0x1, %cl
movb %al, -0x151(%rbp)
jne 0x29671
movq -0x118(%rbp), %rdi
movq -0x60(%rbp), %rax
movq %rax, -0x70(%rbp)
movq -0x70(%rbp), %rsi
callq 0x1bf80
xorb $-0x1, %al
movb %al, -0x151(%rbp)
movb -0x151(%rbp), %al
testb $0x1, %al
jne 0x29680
jmp 0x29702
movq -0x118(%rbp), %rax
movl $0x1, -0x74(%rbp)
movq 0x1010(%rax), %rsi
movl -0x74(%rbp), %edx
leaq -0x90(%rbp), %rdi
callq 0x2aac0
leaq -0x90(%rbp), %rdi
callq 0x2ab10
testb $0x1, %al
jne 0x296f1
movq -0x118(%rbp), %rdi
movl -0x74(%rbp), %esi
leaq -0x90(%rbp), %rdx
callq 0x2ab50
jmp 0x296cc
jmp 0x296f1
movq %rax, %rcx
movl %edx, %eax
movq %rcx, -0x98(%rbp)
movl %eax, -0x9c(%rbp)
leaq -0x90(%rbp), %rdi
callq 0x1cca0
jmp 0x29c4c
leaq -0x90(%rbp), %rdi
callq 0x1cca0
jmp 0x29c43
leaq -0x60(%rbp), %rdi
callq 0x1ba90
testb $0x1, (%rax)
je 0x29a10
leaq -0x60(%rbp), %rdi
callq 0x1ba90
movb $0x0, (%rax)
leaq -0x60(%rbp), %rdi
callq 0x1ba90
movl 0x28(%rax), %eax
movl %eax, -0xa0(%rbp)
leaq -0x60(%rbp), %rdi
callq 0x1ba90
cmpl $0x0, 0x2c(%rax)
je 0x29750
leaq -0x60(%rbp), %rdi
callq 0x1ba90
cmpl $0x1, 0x2c(%rax)
jne 0x2979c
movq -0x118(%rbp), %rax
movq 0x1000(%rax), %rax
movq %rax, -0x160(%rbp)
leaq -0x60(%rbp), %rdi
callq 0x1ba90
movq %rax, %rdi
addq $0x10, %rdi
callq 0x1c170
movq -0x160(%rbp), %rdi
movq %rax, %rsi
movq -0x118(%rbp), %rax
movq 0xff8(%rax), %rcx
movl $0x1, %edx
callq 0x29ea0
movq -0x118(%rbp), %rcx
movq 0x1000(%rcx), %rax
movq 0x390(%rax), %rax
movl 0x260c(%rax), %eax
movq 0x1000(%rcx), %rcx
movq 0x390(%rcx), %rcx
imull 0x2610(%rcx), %eax
movl $0x8, %ecx
cltd
idivl %ecx
movl %eax, -0xa4(%rbp)
leaq -0x60(%rbp), %rdi
callq 0x1ba90
cmpl $0x0, 0x2c(%rax)
jne 0x298f2
movq -0x118(%rbp), %rdi
movq -0x60(%rbp), %rax
movq %rax, -0xb0(%rbp)
movq -0xb0(%rbp), %rsi
callq 0x1f530
testb $0x1, %al
jne 0x29811
jmp 0x2984a
movq -0x118(%rbp), %rdi
addq $0x2f8, %rdi            # imm = 0x2F8
movl -0xa0(%rbp), %esi
callq 0x2ae00
movq %rax, %rdi
callq 0x29c80
movq -0x118(%rbp), %rdi
addq $0x130, %rdi            # imm = 0x130
callq 0x29090
jmp 0x298da
movq -0x118(%rbp), %rdi
movq -0x60(%rbp), %rax
movq %rax, -0xb8(%rbp)
movq -0xb8(%rbp), %rsi
callq 0x2ae30
testb $0x1, %al
jne 0x2986e
jmp 0x298a4
movq -0x118(%rbp), %rdi
addq $0x458, %rdi            # imm = 0x458
movl -0xa0(%rbp), %esi
callq 0x2ae00
movq %rax, %rdi
callq 0x29c80
movq -0x118(%rbp), %rdi
addq $0x260, %rdi            # imm = 0x260
callq 0x29090
jmp 0x298d8
movq -0x118(%rbp), %rdi
addq $0x3a8, %rdi            # imm = 0x3A8
movl -0xa0(%rbp), %esi
callq 0x2ae00
movq %rax, %rdi
callq 0x29c80
movq -0x118(%rbp), %rdi
addq $0x1c8, %rdi            # imm = 0x1C8
callq 0x29090
jmp 0x298da
movq -0x118(%rbp), %rdi
leaq -0xa4(%rbp), %rsi
callq 0x29180
jmp 0x29a0e
leaq -0x60(%rbp), %rdi
callq 0x1ba90
cmpl $0x1, 0x2c(%rax)
jne 0x29a0c
movq -0x118(%rbp), %rdi
movq -0x60(%rbp), %rax
movq %rax, -0xc0(%rbp)
movq -0xc0(%rbp), %rsi
callq 0x1f530
testb $0x1, %al
jne 0x29929
jmp 0x29962
movq -0x118(%rbp), %rdi
addq $0x508, %rdi            # imm = 0x508
movl -0xa0(%rbp), %esi
callq 0x2ae00
movq %rax, %rdi
callq 0x29c80
movq -0x118(%rbp), %rdi
addq $0x130, %rdi            # imm = 0x130
callq 0x29090
jmp 0x299f2
movq -0x118(%rbp), %rdi
movq -0x60(%rbp), %rax
movq %rax, -0xc8(%rbp)
movq -0xc8(%rbp), %rsi
callq 0x2ae30
testb $0x1, %al
jne 0x29986
jmp 0x299bc
movq -0x118(%rbp), %rdi
addq $0x668, %rdi            # imm = 0x668
movl -0xa0(%rbp), %esi
callq 0x2ae00
movq %rax, %rdi
callq 0x29c80
movq -0x118(%rbp), %rdi
addq $0x260, %rdi            # imm = 0x260
callq 0x29090
jmp 0x299f0
movq -0x118(%rbp), %rdi
addq $0x5b8, %rdi            # imm = 0x5B8
movl -0xa0(%rbp), %esi
callq 0x2ae00
movq %rax, %rdi
callq 0x29c80
movq -0x118(%rbp), %rdi
addq $0x1c8, %rdi            # imm = 0x1C8
callq 0x29090
jmp 0x299f2
movq -0x118(%rbp), %rdi
addq $0x98, %rdi
leaq -0xa4(%rbp), %rsi
callq 0x29180
jmp 0x29a0e
jmp 0x29a10
movq -0x118(%rbp), %rdi
movq -0x60(%rbp), %rax
movq %rax, -0xd8(%rbp)
movq -0xd8(%rbp), %rsi
callq 0x1c000
movq -0x118(%rbp), %rsi
movl %eax, -0xcc(%rbp)
movl -0xcc(%rbp), %edx
movl %edx, -0x16c(%rbp)
movq -0x60(%rbp), %rax
movq %rax, -0xf8(%rbp)
movq -0xf8(%rbp), %rcx
leaq -0xf0(%rbp), %rdi
movq %rdi, -0x168(%rbp)
callq 0x2aec0
movq -0x118(%rbp), %rdi
movl -0x16c(%rbp), %esi
movq -0x168(%rbp), %rdx
callq 0x2ab50
jmp 0x29a87
leaq -0xf0(%rbp), %rdi
callq 0x1cca0
movq -0x118(%rbp), %rax
movl -0xcc(%rbp), %ecx
movl %ecx, -0x170(%rbp)
movq 0x1000(%rax), %rax
movq 0x390(%rax), %rax
movq %rax, -0x178(%rbp)
leaq -0x60(%rbp), %rdi
callq 0x1ba90
movq -0x178(%rbp), %rcx
movq %rax, %rdx
movl -0x170(%rbp), %eax
movslq 0x2c(%rdx), %rdx
cmpl 0x1c4(%rcx,%rdx,4), %eax
je 0x29b09
jmp 0x29c43
movq %rax, %rcx
movl %edx, %eax
movq %rcx, -0x98(%rbp)
movl %eax, -0x9c(%rbp)
leaq -0xf0(%rbp), %rdi
callq 0x1cca0
jmp 0x29c4c
leaq -0x60(%rbp), %rdi
callq 0x1ba90
cmpl $0x0, 0x2c(%rax)
jne 0x29bb3
movq -0x118(%rbp), %rax
movq 0xff8(%rax), %rcx
movq %rcx, -0x190(%rbp)
movq 0x1000(%rax), %rcx
movq 0x390(%rcx), %rcx
movq 0x1000(%rax), %rax
movl 0x39c(%rax), %eax
movl $0x4, %esi
cltd
idivl %esi
movq -0x190(%rbp), %rax
movslq %edx, %rdx
movslq 0x276c(%rcx,%rdx,4), %rcx
addq %rcx, %rax
movq %rax, -0x188(%rbp)
leaq -0x60(%rbp), %rdi
callq 0x1ba90
movq -0x188(%rbp), %rdx
movq %rax, %rcx
movq -0x118(%rbp), %rax
movq %rdx, 0x38(%rcx)
addq $0x1088, %rax           # imm = 0x1088
movq %rax, -0x180(%rbp)
leaq -0x60(%rbp), %rdi
callq 0x2af70
movq -0x180(%rbp), %rdi
movq %rax, %rsi
callq 0x2af10
leaq -0x60(%rbp), %rdi
callq 0x1ba90
cmpl $0x1, 0x2c(%rax)
jne 0x29c0e
movq -0x118(%rbp), %rax
movq 0x1000(%rax), %rax
movq %rax, -0x198(%rbp)
leaq -0x60(%rbp), %rdi
callq 0x1ba90
movq %rax, %rdi
addq $0x10, %rdi
callq 0x1c170
movq -0x198(%rbp), %rdi
movq %rax, %rsi
movq -0x118(%rbp), %rax
movq 0xff8(%rax), %rcx
movl $0xffffffff, %edx       # imm = 0xFFFFFFFF
callq 0x29ea0
movq -0x58(%rbp), %rax
movq %rax, -0x1a0(%rbp)
leaq -0x100(%rbp), %rdi
leaq -0x60(%rbp), %rsi
callq 0x2afe0
movq -0x1a0(%rbp), %rdi
movq -0x100(%rbp), %rsi
callq 0x2af90
movq %rax, -0x108(%rbp)
addq $0x1a0, %rsp            # imm = 0x1A0
popq %rbp
retq
movq -0x98(%rbp), %rdi
callq 0x65b0
nopl (%rax,%rax)