docstr: Write a top level HLS C++ file to wrap the hls4ml project with AXI interfaces
  Args:
      model : The ModelGraph to write the wrapper for
docstr_tok: ["Write","a","top","level","HLS","C++","file","to","wrap","the","hls4ml","project","with","AXI","interfaces","Args",":","model",":","The","ModelGraph","to","write","the","wrapper","for"]
code: def write_axi_wrapper(self, model):
      """Write a top level HLS C++ file to wrap the hls4ml project with AXI interfaces
      Args:
          model : The ModelGraph to write the wrapper for
      """
      (
          inp_axi_t,
          out_axi_t,
          inp,
          out,
      ) = self.vivado_accelerator_config.get_corrected_types()
      indent = "    "
  
      #######################
      # myproject_axi.h
      #######################
  
      filedir = os.path.dirname(os.path.abspath(__file__))
      f = open(
          os.path.join(
              filedir, "../templates/vivado_accelerator/myproject_axi.h"
          )
      )
      fout = open(
          f"{model.config.get_output_dir()}/firmware/{model.config.get_project_name()}_axi.h",
          "w",
      )
  
      for line in f.readlines():
          if "MYPROJECT" in line:
              newline = line.replace(
                  "MYPROJECT",
                  format(model.config.get_project_name().upper()),
              )
          elif "// hls-fpga-machine-learning insert include" in line:
              newline = (
                  f'#include "{model.config.get_project_name()}.h"\n'
              )
          elif "myproject" in line:
              newline = line.replace(
                  "myproject", model.config.get_project_name()
              )
          elif (
              "// hls-fpga-machine-learning insert definitions" in line
          ):
              newline = ""
              newline += f"static const unsigned N_IN = {inp.size()};\n"
              newline += (
                  f"static const unsigned N_OUT = {out.size()};\n"
              )
              if (
                  self.vivado_accelerator_config.get_interface()
                  == "axi_stream"
              ):
                  newline += f"typedef {inp_axi_t} T_in;\n"
                  newline += f"typedef {out_axi_t} T_out;\n"
                  newline += (
                      "typedef struct in_struct {\n"
                      + indent
                      + "T_in data;\n"
                      + indent
                      + "ap_uint<1> last;\n"
                      + indent
                      + "in_struct(const T_in& data, const ap_uint<1>& last){this->data = data; this->last = last;};\n"
                      + indent
                      + "in_struct(){this->data = 0; this->last = 0;};\n"
                      + indent
                      + "friend std::ostream& operator<<(std::ostream& stream, const in_struct& in)\n"
                      + indent
                      + '{ return stream << "{ data: " << in.data << ", last: " << in.last << " }" << std::endl; }\n'
                      + indent
                      + "operator float() const {return this->data;}\n"
                      + indent
                      + "operator double() const {return this->data;}\n"
                      + indent
                      + "in_struct(float data) {this->data = data; this->last = 0;}\n"
                      + indent
                      + "in_struct(double data) {this->data = data; this->last = 0;}\n"
                      + "} input_axi_t;\n"
                  )
                  newline += (
                      "typedef struct out_struct {\n"
                      + indent
                      + "T_out data;\n"
                      + indent
                      + "ap_uint<1> last;\n"
                      + indent
                      + "out_struct(const T_out& data, const ap_uint<1>& last){this->data = data; this->last = last;};\n"
                      + indent
                      + "out_struct(){this->data = 0; this->last = 0;};\n"
                      + indent
                      + "friend std::ostream& operator<<(std::ostream& stream, const out_struct& out)\n"
                      + indent
                      + '{ return stream << "{ data: " << out.data << ", last: " << out.last << " }" << std::endl; }\n'
                      + indent
                      + "operator float() const {return this->data;}\n"
                      + indent
                      + "operator double() const {return this->data;}\n"
                      + indent
                      + "out_struct(float data) {this->data = data; this->last = 0;}\n"
                      + indent
                      + "out_struct(double data) {this->data = data; this->last = 0;}\n"
                      + "} output_axi_t;\n"
                  )
              else:
                  newline += f"typedef {inp_axi_t} input_axi_t;\n"
                  newline += f"typedef {out_axi_t} output_axi_t;\n"
          else:
              newline = line
          fout.write(newline)
      f.close()
      fout.close()
  
      #######################
      # myproject_axi.cpp
      #######################
  
      f = open(
          os.path.join(
              filedir,
              "../templates/vivado_accelerator/myproject_axi.cpp",
          )
      )
      fout = open(
          f"{model.config.get_output_dir()}/firmware/{model.config.get_project_name()}_axi.cpp",
          "w",
      )
  
      io_type = model.config.get_config_value("IOType")
  
      for line in f.readlines():
          if "myproject" in line:
              newline = line.replace(
                  "myproject", model.config.get_project_name()
              )
          elif "// hls-fpga-machine-learning insert include" in line:
              newline = f'#include "{model.config.get_project_name()}_axi.h"\n'
          elif "// hls-fpga-machine-learning insert local vars" in line:
              newline = ""
              if (
                  self.vivado_accelerator_config.get_interface()
                  == "axi_stream"
              ):
                  newline += indent + "bool is_last = false;\n"
              if io_type == "io_parallel":
                  newline += (
                      indent + inp.type.name + " in_local[N_IN];\n"
                  )
                  newline += (
                      indent + out.type.name + " out_local[N_OUT];\n"
                  )
              elif io_type == "io_stream":
                  newline += (
                      indent
                      + "hls::stream<"
                      + inp.type.name
                      + '> in_local("input_1");\n'
                  )
                  newline += (
                      indent
                      + "hls::stream<"
                      + out.type.name
                      + '> out_local("output_1");\n\n'
                  )
                  newline += (
                      indent
                      + "#pragma HLS STREAM variable=in_local depth={}\n".format(
                          model.get_input_variables()[0].pragma[1]
                      )
                  )
                  newline += (
                      indent
                      + "#pragma HLS STREAM variable=out_local depth={}\n".format(
                          model.get_output_variables()[0].pragma[1]
                      )
                  )
          elif "// hls-fpga-machine-learning insert call" in line:
              newline = (
                  indent
                  + f"{model.config.get_project_name()}(in_local, out_local);\n"
              )
          elif "// hls-fpga-machine-learning insert interface" in line:
              if (
                  self.vivado_accelerator_config.get_interface()
                  == "axi_lite"
              ):
                  newline = ""
                  newline += (
                      indent
                      + "#pragma HLS INTERFACE ap_ctrl_none port=return\n"
                  )
                  newline += (
                      indent
                      + "#pragma HLS INTERFACE s_axilite port=in\n"
                  )
                  newline += (
                      indent
                      + "#pragma HLS INTERFACE s_axilite port=out\n"
                  )
              elif (
                  self.vivado_accelerator_config.get_interface()
                  == "axi_master"
              ):
                  newline = ""
                  newline += (
                      indent
                      + "#pragma HLS INTERFACE s_axilite port=return bundle=CTRL_BUS\n"
                  )
                  newline += (
                      indent
                      + "#pragma HLS INTERFACE m_axi depth={} port=in offset=slave bundle=IN_BUS\n".format(
                          model.get_input_variables()[0].pragma[1]
                      )
                  )
                  newline += (
                      indent
                      + "#pragma HLS INTERFACE m_axi depth={} port=out offset=slave bundle=OUT_BUS\n".format(
                          model.get_output_variables()[0].pragma[1]
                      )
                  )
              elif (
                  self.vivado_accelerator_config.get_interface()
                  == "axi_stream"
              ):
                  newline = ""
                  newline += (
                      indent + "#pragma HLS INTERFACE axis port=in\n"
                  )
                  newline += (
                      indent + "#pragma HLS INTERFACE axis port=out\n"
                  )
                  newline += (
                      indent
                      + "#pragma HLS INTERFACE ap_ctrl_none port=return\n"
                  )
                  if (
                      model.config.get_config_value("IOType")
                      == "io_stream"
                  ):
                      newline += indent + "#pragma HLS DATAFLOW\n"
          elif "// hls-fpga-machine-learning insert enqueue" in line:
              io_type = model.config.get_config_value("IOType")
              if io_type == "io_parallel":
                  newline = ""
                  newline += (
                      indent + "for(unsigned i = 0; i < N_IN; i++){\n"
                  )
                  if (
                      self.vivado_accelerator_config.get_interface()
                      == "axi_stream"
                  ):
                      newline += (
                          indent + indent + "#pragma HLS PIPELINE\n"
                      )
                      newline += (
                          indent
                          + indent
                          + "in_local[i] = in[i].data; // Read input with cast\n"
                      )
                      newline += (
                          indent
                          + indent
                          + "is_last |= (in[i].last == 1)? true: false;\n"
                      )
                  else:
                      newline += (
                          indent + indent + "#pragma HLS UNROLL\n"
                      )
                      newline += (
                          indent
                          + indent
                          + "in_local[i] = in[i]; // Read input with cast\n"
                      )
                  newline += indent + "}\n"
              elif io_type == "io_stream":
                  newline = ""
                  newline += (
                      indent
                      + "for(unsigned i = 0; i < N_IN / {input_t}::size; ++i) {{\n"
                  )
                  # newline += indent + indent + '#pragma HLS PIPELINE\n'
                  newline += indent + indent + "{input_t} ctype;\n"
                  newline += (
                      indent
                      + indent
                      + "#pragma HLS DATA_PACK variable=ctype\n"
                  )
                  newline += (
                      indent
                      + indent
                      + "for(unsigned j = 0; j < {input_t}::size; j++) {{\n"
                  )
                  # newline += indent + indent + indent + '#pragma HLS UNROLL\n'
                  if (
                      self.vivado_accelerator_config.get_interface()
                      == "axi_stream"
                  ):
                      newline += (
                          indent
                          + indent
                          + indent
                          + "ctype[j] = typename {input_t}::value_type(in[i * {input_t}::size + j].data);\n"
                      )
                      newline += (
                          indent
                          + indent
                          + indent
                          + "is_last |= (in[i * input_t::size + j].last == 1)? true : false;\n"
                      )
                  else:
                      newline += (
                          indent
                          + indent
                          + indent
                          + "ctype[j] = typename {input_t}::value_type(in[i * {input_t}::size + j]);\n"
                      )
                  newline += indent + indent + "}}\n"
                  newline += (
                      indent + indent + "in_local.write(ctype);\n"
                  )
                  newline += indent + "}}\n"
                  newline = newline.format(input_t=inp.type.name)
          elif "// hls-fpga-machine-learning insert dequeue" in line:
              io_type = model.config.get_config_value("IOType")
              if io_type == "io_parallel":
                  newline = ""
                  newline += (
                      indent + "for(unsigned i = 0; i < N_OUT; i++){\n"
                  )
                  if (
                      self.vivado_accelerator_config.get_interface()
                      == "axi_stream"
                  ):
                      newline += (
                          indent + indent + "#pragma HLS PIPELINE\n"
                      )
                      newline += (
                          indent
                          + indent
                          + "out[i].data = out_local[i]; // Write output with cast\n"
                      )
                      newline += (
                          indent
                          + indent
                          + "out[i].last = (is_last && (i == N_OUT - 1))? true : false;\n"
                      )
                  else:
                      newline += (
                          indent + indent + "#pragma HLS UNROLL\n"
                      )
                      newline += (
                          indent
                          + indent
                          + "out[i] = out_local[i]; // Write output with cast\n"
                      )
                  newline += indent + "}\n"
              elif io_type == "io_stream":
                  newline = ""
                  newline += (
                      indent
                      + "for(unsigned i = 0; i < N_OUT / {result_t}::size; ++i) {{\n"
                  )
                  # newline += indent + indent + '#pragma HLS PIPELINE\n'
                  newline += (
                      indent
                      + indent
                      + "{result_t} ctype = out_local.read();\n"
                  )
                  newline += (
                      indent
                      + indent
                      + "for(unsigned j = 0; j < {result_t}::size; j++) {{\n"
                  )
                  # newline += indent + indent + indent + '#pragma HLS UNROLL\n'
                  if (
                      self.vivado_accelerator_config.get_interface()
                      == "axi_stream"
                  ):
                      newline += (
                          indent
                          + indent
                          + indent
                          + "bool last = (is_last && (i * {result_t}::size + j == N_OUT - 1)) ? true : false;\n"
                      )
                      newline += (
                          indent
                          + indent
                          + indent
                          + "out[i * {result_t}::size + j] = output_axi_t(ctype[j], last);\n"
                      )
                  else:
                      newline += (
                          indent
                          + indent
                          + indent
                          + "out[i * {result_t}::size + j] = output_axi_t(ctype[j]);\n"
                      )
                  newline += indent + indent + "}}\n"
                  newline += indent + "}}\n"
                  newline = newline.format(result_t=out.type.name)
          else:
              newline = line
          fout.write(newline)
      f.close()
      fout.close()
  
file_path: hls4ml/hls4ml/writer/vivado_accelerator_writer.py
imports: import os
  from distutils.dir_util import copy_tree
  from shutil import copyfile
  from hls4ml.writer.vivado_writer import VivadoWriter
label_desc: Use image node_id 2 for calling the VivadoAcceleratorWriter obj's underlying member method code with example usage: obj.write_axi_wrapper(model) without return types