docstr: Write the main architecture source file (myproject.cpp)
  
  Args:
      model (ModelGraph): the hls4ml model.
docstr_tok: ["Write","the","main","architecture","source","file","(","myproject.cpp",")","Args",":","model","(","ModelGraph",")",":","the","hls4ml","model","."]
code: def write_project_cpp(self, model):
      """Write the main architecture source file (myproject.cpp)
  
      Args:
          model (ModelGraph): the hls4ml model.
      """
  
      filedir = os.path.dirname(os.path.abspath(__file__))
  
      f = open(
          os.path.join(
              filedir, "../templates/vivado/firmware/myproject.cpp"
          )
      )
      fout = open(
          f"{model.config.get_output_dir()}/firmware/{model.config.get_project_name()}.cpp",
          "w",
      )
  
      model_inputs = model.get_input_variables()
      model_outputs = model.get_output_variables()
      model_brams = [
          var
          for var in model.get_weight_variables()
          if var.storage.lower() == "bram"
      ]
  
      indent = "    "
  
      for line in f.readlines():
          # Add headers to weights and biases
          if "myproject" in line:
              newline = line.replace(
                  "myproject", model.config.get_project_name()
              )
          elif "// hls-fpga-machine-learning insert header" in line:
              inputs_str = ", ".join(
                  [
                      i.definition_cpp(as_reference=True)
                      for i in model_inputs
                  ]
              )
              outputs_str = ", ".join(
                  [
                      o.definition_cpp(as_reference=True)
                      for o in model_outputs
                  ]
              )
              brams_str = ", \n".join(
                  [
                      indent + b.definition_cpp(as_reference=False)
                      for b in model_brams
                  ]
              )
  
              newline = ""
              newline += indent + inputs_str + ",\n"
              newline += indent + outputs_str
              if len(model_brams) > 0:
                  newline += ",\n" + brams_str
              newline += "\n"
  
          elif (
              "// hls-fpga-machine-learning insert load weights" in line
          ):
              newline = line
              for layer in model.get_layers():
                  for w in layer.get_weights():
                      if w.weight_class == "CompressedWeightVariable":
                          newline += (
                              indent
                              + '    nnet::load_compressed_weights_from_txt<{}, {}>({}, "{}.txt");\n'.format(
                                  w.type.name,
                                  w.nonzeros,
                                  w.name,
                                  w.name,
                              )
                          )
                      elif w.weight_class == "ExponentWeightVariable":
                          newline += (
                              indent
                              + '    nnet::load_exponent_weights_from_txt<{}, {}>({}, "{}.txt");\n'.format(
                                  w.type.name,
                                  w.data_length,
                                  w.name,
                                  w.name,
                              )
                          )
                      else:
                          newline += (
                              indent
                              + '    nnet::load_weights_from_txt<{}, {}>({}, "{}.txt");\n'.format(
                                  w.type.name,
                                  w.data_length,
                                  w.name,
                                  w.name,
                              )
                          )
  
          # Add input/output type
          elif "// hls-fpga-machine-learning insert IO" in line:
              newline = line
              all_inputs = [i.name for i in model_inputs]
              all_outputs = [o.name for o in model_outputs]
              all_brams = [b.name for b in model_brams]
              io_type = model.config.get_config_value("IOType")
  
              if io_type == "io_parallel":
                  for i in model_inputs:
                      newline += (
                          indent + self._make_array_pragma(i) + "\n"
                      )
                  for o in model_outputs:
                      newline += (
                          indent + self._make_array_pragma(o) + "\n"
                      )
                  # TODO discussed adding a handle for setting the interface mode for individual input and output arrays
                  # Probably the handle doesn't need to be exposed to the user but should be just set in hls_model.py
                  newline += (
                      indent
                      + "#pragma HLS INTERFACE ap_vld port={},{} \n".format(
                          ",".join(all_inputs), ",".join(all_outputs)
                      )
                  )
                  if model.config.pipeline_style.lower() == "dataflow":
                      newline += indent + "#pragma HLS DATAFLOW \n"
                  else:
                      newline += indent + "#pragma HLS PIPELINE \n"
              if io_type == "io_stream":
                  newline += (
                      indent
                      + "#pragma HLS INTERFACE axis port={},{} \n".format(
                          ",".join(all_inputs), ",".join(all_outputs)
                      )
                  )
                  if all_brams:
                      newline += (
                          indent
                          + "#pragma HLS INTERFACE bram port={} \n".format(
                              ",".join(all_brams)
                          )
                      )
                  newline += indent + "#pragma HLS DATAFLOW \n"
  
          elif "// hls-fpga-machine-learning insert layers" in line:
              newline = line + "\n"
              for layer in model.get_layers():
                  vars = layer.get_variables()
                  for var in vars:
                      if (
                          var not in model_inputs
                          and var not in model_outputs
                      ):
                          def_cpp = var.definition_cpp()
                          if def_cpp is not None:
                              newline += "    " + def_cpp + ";\n"
                              if var.pragma:
                                  newline += (
                                      "    "
                                      + self._make_array_pragma(var)
                                      + "\n"
                                  )
                  func = layer.get_attr("function_cpp", None)
                  if func:
                      if not isinstance(func, (list, set)):
                          func = [func]
                      if len(func) == 1:
                          newline += (
                              "    "
                              + func[0]
                              + " // "
                              + layer.name
                              + "\n"
                          )
                      else:
                          newline += "    // " + layer.name + "\n"
                          for line in func:
                              newline += "    " + line + "\n"
                      if model.config.trace_output and layer.get_attr(
                          "trace", False
                      ):
                          newline += "#ifndef __SYNTHESIS__\n"
                          for var in vars:
                              newline += '    nnet::save_layer_output<{}>({}, "{}", {});\n'.format(
                                  var.type.name,
                                  var.name,
                                  layer.name,
                                  var.size_cpp(),
                              )
                          newline += "#endif\n"
                      newline += "\n"
  
          # Just copy line
          else:
              newline = line
  
          fout.write(newline)
  
      f.close()
      fout.close()
  
imports: import glob
  import os
  import tarfile
  from collections import OrderedDict
  from shutil import copyfile, copytree, rmtree
  import numpy
  import yaml
  from hls4ml.writer.writers import Writer
label_desc: Use image node_id 4 for calling the VivadoWriter obj's underlying member method code with example usage: obj.write_project_cpp(model) without return types