################################################################################
################ Create FPGA files for on-chip test mapping ####################
################################################################################
import sys, os
import math

import numpy as np
from chip_files.make_mif_fpga import make_mif_fpga

def create_fpga_files(filename_vec,network_info,cim_dim,D_VEC,P_VEC,dataTensors):
  # // Retrieve variables //
  # CNN network info
  Nlayers_cim = network_info[0];
  Nlayers_fp  = network_info[1];
  # CIM dims
  N_ROWS = cim_dim[0];
  N_COLS = cim_dim[1];
  # Channels
  C_IN    = D_VEC[2];
  C_OUT   = D_VEC[3];
  # Precisions
  R_IN    = P_VEC[0];
  R_W     = P_VEC[1];
  R_OUT   = P_VEC[2];
  R_BETA  = P_VEC[3];
  R_GAMMA = P_VEC[4];
  # Data
  data_in     = dataTensors[0];
  data_w_cim  = dataTensors[1];
  data_b_cim  = dataTensors[2];
  data_w_fp   = dataTensors[3];
  data_inf    = dataTensors[4];
  if(len(dataTensors) > 5):
    data_out  = dataTensors[5];
  # Files to write
  filename_in     = filename_vec[0];
  filename_w_cim  = filename_vec[1];
  filename_b_cim  = filename_vec[2];
  filename_w_fp   = filename_vec[3];
  filename_inf    = filename_vec[4];
  if(len(dataTensors) > 5):
    filename_out    = filename_vec[5];
  
  # Internal variables
  Ndata = np.shape(data_in);  Ndata = Ndata[0];
  
  # // Extract beta-offset bits to pack them coluwm-wise //
  beta_conf_list = [];
  for i in range(Nlayers_cim):
    beta_conf_temp = np.expand_dims(data_b_cim[i].astype("uint8"),axis=-1); 
    beta_unpacked = np.flip(np.unpackbits(beta_conf_temp,axis=-1),axis=-1);
    # swap axes
    beta_unpacked = np.swapaxes(beta_unpacked,0,1);
    # Repeat beta values in r_w cols
    beta_unpacked = np.repeat(beta_unpacked,R_W,axis=-1);
    if(R_W*C_OUT[i] < 32):
      beta_unpacked = np.pad(beta_unpacked,((0,0),(0,32-R_W*C_OUT[i])));
    beta_conf_temp = np.dot(np.reshape(beta_unpacked[:R_BETA,...],(-1,32)),2**np.arange(32));
    beta_conf_list.append(beta_conf_temp);
  #Stack results along a single dimension
  data_b_cim = np.stack(beta_conf_list);
  
  # // Write fpga test files //
  make_mif_fpga(filename_in,data_in,32);
  make_mif_fpga(filename_w_cim,data_w_cim,32);
  make_mif_fpga(filename_b_cim,data_b_cim,32);
  make_mif_fpga(filename_w_fp,data_w_fp,32);
  make_mif_fpga(filename_inf,data_inf,8);
  if(len(dataTensors) > 5):
    make_mif_fpga(filename_out,data_out,32);
  
  
  return;