// File: MPSLab-ASU[P]DiRAC/./src/controller.cc
// Function: controller::write_back_controller(unsigned short)
void controller::write_back_controller(uint16_t current_RF_pass)
{
  assert(PE_writeback_RF_incomplete == 1 && "Communication of data from PEs to controller is incomplete.");
  bool writeback_completed = true;

  for(uint8_t i=0; i < outNetworks; i++) {

    network_write_op_comm_completed[i] = 1;

    if(write_data_RF_pass[current_RF_pass][i])
    {
      // schedule writeback of operand to PE
      if(cnt_writeback_via_network_RF_pass[i] < RF_pass_network_write_operand[current_RF_pass][i].size())
      {
        uint16_t burst_size_op = RF_pass_network_write_operand_burst_width_elements[current_RF_pass][i][cnt_writeback_via_network_RF_pass[i]];
        network_write_op_comm_completed[i] = 0; // communication incomplete yet.
        if(idx_write_network_packet[i] < burst_size_op) {
          if(is_data_collected[i]) {
            uint8_t operand = RF_pass_network_write_operand[current_RF_pass][i][cnt_writeback_via_network_RF_pass[i]];
            uint8_t buffer_number_comp = spm_buffer_number_op_comp_write[operand];
            uint16_t offset_data_collect = config_data_collect_write_back[i][idx_write_network_packet[i]];
            uint32_t offset_SPM = RF_pass_network_write_operand_offset_base_addr_SPM[current_RF_pass][i][cnt_writeback_via_network_RF_pass[i]];
            uint32_t address_SPM = ((operand_start_addr_SPM_buffer[buffer_number_comp][operand] + offset_SPM) / sizeof(data_type)) + offset_data_collect;
            scratchpad_mem->write(address_SPM, collected_data[i]);
            idx_write_network_packet[i] += 1;
          }
        }
        else {
          cnt_writeback_via_network_RF_pass[i] += 1;
          idx_write_network_packet[i] = 0;
        }
      }
    }
    writeback_completed &= (network_write_op_comm_completed[i] == 1);
  }

  counter_RF_pass_writeback += 1;

  if ((counter_RF_pass_writeback >= total_cycles_RF_pass) && (writeback_completed)) {
    PE_writeback_RF_incomplete = false;
    for(uint8_t i=0; i < inNetworks; i++)
      cnt_writeback_via_network_RF_pass[i] = 0;
  }
}

// Assembly:
pushq %rbp
movq %rsp, %rbp
subq $0x30, %rsp
movw %si, %ax
movq %rdi, -0x8(%rbp)
movw %ax, -0xa(%rbp)
movq -0x8(%rbp), %rax
movq %rax, -0x28(%rbp)
movb 0xcf(%rax), %al
andb $0x1, %al
movzbl %al, %ecx
xorl %eax, %eax
cmpl $0x1, %ecx
movb %al, -0x1e(%rbp)
jne 0x4180b7
movb $0x1, %al
movb %al, -0x1e(%rbp)
jmp 0x4180b7
movb -0x1e(%rbp), %al
testb $0x1, %al
jne 0x4180c0
jmp 0x4180c2
jmp 0x4180e1
leaq 0x18b8fa(%rip), %rdi    # 0x5a39c3
leaq 0x18b63d(%rip), %rsi    # 0x5a370d
movl $0x26b, %edx            # imm = 0x26B
leaq 0x18b948(%rip), %rcx    # 0x5a3a24
callq 0x4e53d0
movb $0x1, -0xb(%rbp)
movb $0x0, -0xc(%rbp)
movzbl -0xc(%rbp), %eax
movq $0x61e5e4, %rcx         # imm = 0x61E5E4
movzbl (%rcx), %ecx
cmpl %ecx, %eax
jge 0x418399
movq -0x28(%rbp), %rax
movq 0x108(%rax), %rax
movzbl -0xc(%rbp), %ecx
movb $0x1, (%rax,%rcx)
movq $0x61e6b0, %rax         # imm = 0x61E6B0
movq (%rax), %rax
movzwl -0xa(%rbp), %ecx
movq (%rax,%rcx,8), %rax
movzbl -0xc(%rbp), %ecx
testb $0x1, (%rax,%rcx)
je 0x418355
movq -0x28(%rbp), %rax
movq 0xe0(%rax), %rax
movzbl -0xc(%rbp), %ecx
movzbl (%rax,%rcx), %eax
movq %rax, -0x30(%rbp)
movq $0x61e6b8, %rax         # imm = 0x61E6B8
movq (%rax), %rax
movzwl -0xa(%rbp), %ecx
movq (%rax,%rcx,8), %rdi
movzbl -0xc(%rbp), %eax
imulq $0x18, %rax, %rax
addq %rax, %rdi
callq 0x4143b0
movq %rax, %rcx
movq -0x30(%rbp), %rax
cmpq %rcx, %rax
jae 0x418353
movq -0x28(%rbp), %rax
movq $0x61e6c8, %rcx         # imm = 0x61E6C8
movq (%rcx), %rcx
movzwl -0xa(%rbp), %edx
movq (%rcx,%rdx,8), %rdi
movzbl -0xc(%rbp), %ecx
imulq $0x18, %rcx, %rcx
addq %rcx, %rdi
movq 0xe0(%rax), %rax
movzbl -0xc(%rbp), %ecx
movzbl (%rax,%rcx), %eax
movl %eax, %esi
callq 0x4189e0
movq %rax, %rcx
movq -0x28(%rbp), %rax
movl (%rcx), %ecx
movw %cx, -0xe(%rbp)
movq 0x108(%rax), %rcx
movzbl -0xc(%rbp), %edx
movb $0x0, (%rcx,%rdx)
movq 0xf0(%rax), %rax
movzbl -0xc(%rbp), %ecx
movzwl (%rax,%rcx,2), %eax
movzwl -0xe(%rbp), %ecx
cmpl %ecx, %eax
jge 0x418326
movq -0x28(%rbp), %rax
movq 0x110(%rax), %rax
movzbl -0xc(%rbp), %ecx
testb $0x1, (%rax,%rcx)
je 0x418324
movq -0x28(%rbp), %rax
movq $0x61e6b8, %rcx         # imm = 0x61E6B8
movq (%rcx), %rcx
movzwl -0xa(%rbp), %edx
movq (%rcx,%rdx,8), %rdi
movzbl -0xc(%rbp), %ecx
imulq $0x18, %rcx, %rcx
addq %rcx, %rdi
movq 0xe0(%rax), %rax
movzbl -0xc(%rbp), %ecx
movzbl (%rax,%rcx), %eax
movl %eax, %esi
callq 0x418c60
movq %rax, %rcx
movq -0x28(%rbp), %rax
movb (%rcx), %cl
movb %cl, -0xf(%rbp)
movq $0x61e730, %rcx         # imm = 0x61E730
movq (%rcx), %rcx
movzbl -0xf(%rbp), %edx
movb (%rcx,%rdx), %cl
movb %cl, -0x10(%rbp)
movq $0x61e608, %rcx         # imm = 0x61E608
movq (%rcx), %rcx
movzbl -0xc(%rbp), %edx
movq (%rcx,%rdx,8), %rcx
movq 0xf0(%rax), %rdx
movzbl -0xc(%rbp), %esi
movzwl (%rdx,%rsi,2), %edx
movw (%rcx,%rdx,2), %cx
movw %cx, -0x12(%rbp)
movq $0x61e6d0, %rcx         # imm = 0x61E6D0
movq (%rcx), %rcx
movzwl -0xa(%rbp), %edx
movq (%rcx,%rdx,8), %rdi
movzbl -0xc(%rbp), %ecx
imulq $0x18, %rcx, %rcx
addq %rcx, %rdi
movq 0xe0(%rax), %rax
movzbl -0xc(%rbp), %ecx
movzbl (%rax,%rcx), %eax
movl %eax, %esi
callq 0x4189e0
movq %rax, %rcx
movq -0x28(%rbp), %rax
movl (%rcx), %ecx
movl %ecx, -0x18(%rbp)
movq $0x61e640, %rcx         # imm = 0x61E640
movq (%rcx), %rcx
movzbl -0x10(%rbp), %edx
movq (%rcx,%rdx,8), %rcx
movzbl -0xf(%rbp), %edx
movl (%rcx,%rdx,4), %ecx
addl -0x18(%rbp), %ecx
movl %ecx, %ecx
shrq %rcx
movzwl -0x12(%rbp), %edx
addq %rdx, %rcx
movl %ecx, -0x1c(%rbp)
movq 0xb0(%rax), %rdi
movl -0x1c(%rbp), %esi
movq 0x118(%rax), %rax
movzbl -0xc(%rbp), %ecx
movzwl (%rax,%rcx,2), %edx
callq 0x424570
movq -0x28(%rbp), %rax
movq 0xf0(%rax), %rax
movzbl -0xc(%rbp), %ecx
movzwl (%rax,%rcx,2), %edx
addl $0x1, %edx
movw %dx, (%rax,%rcx,2)
jmp 0x418351
movq -0x28(%rbp), %rax
movq 0xe0(%rax), %rcx
movzbl -0xc(%rbp), %edx
movzbl (%rcx,%rdx), %esi
addl $0x1, %esi
movb %sil, (%rcx,%rdx)
movq 0xf0(%rax), %rax
movzbl -0xc(%rbp), %ecx
movw $0x0, (%rax,%rcx,2)
jmp 0x418353
jmp 0x418355
movq -0x28(%rbp), %rax
movq 0x108(%rax), %rax
movzbl -0xc(%rbp), %ecx
movb (%rax,%rcx), %al
andb $0x1, %al
movzbl %al, %eax
cmpl $0x1, %eax
sete %al
andb $0x1, %al
movzbl %al, %ecx
movb -0xb(%rbp), %al
andb $0x1, %al
movzbl %al, %eax
andl %ecx, %eax
cmpl $0x0, %eax
setne %al
andb $0x1, %al
movb %al, -0xb(%rbp)
movb -0xc(%rbp), %al
addb $0x1, %al
movb %al, -0xc(%rbp)
jmp 0x4180e9
movq -0x28(%rbp), %rax
movzwl 0xd2(%rax), %ecx
addl $0x1, %ecx
movw %cx, 0xd2(%rax)
movzwl 0xd2(%rax), %eax
movq $0x61e5e0, %rcx         # imm = 0x61E5E0
movzwl (%rcx), %ecx
cmpl %ecx, %eax
jl 0x418409
testb $0x1, -0xb(%rbp)
je 0x418409
movq -0x28(%rbp), %rax
movb $0x0, 0xcf(%rax)
movb $0x0, -0x1d(%rbp)
movzbl -0x1d(%rbp), %eax
movq $0x61c151, %rcx         # imm = 0x61C151
movzbl (%rcx), %ecx
cmpl %ecx, %eax
jge 0x418407
movq -0x28(%rbp), %rax
movq 0xe0(%rax), %rax
movzbl -0x1d(%rbp), %ecx
movb $0x0, (%rax,%rcx)
movb -0x1d(%rbp), %al
addb $0x1, %al
movb %al, -0x1d(%rbp)
jmp 0x4183d8
jmp 0x418409
addq $0x30, %rsp
popq %rbp
retq
nop