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.
      """
      project_name = model.config.get_project_name()
  
      filedir = os.path.dirname(os.path.abspath(__file__))
      f = open(
          os.path.join(
              filedir, "../templates/quartus/firmware/myproject.cpp"
          )
      )
      fout = open(
          f"{model.config.get_output_dir()}/firmware/{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"
      ]
  
      io_type = model.config.get_config_value("IOType")
      indent = "   "
      brams_str = ", \n".join(
          [
              indent + b.definition_cpp(as_reference=False)
              for b in model_brams
          ]
      )
  
      for line in f.readlines():
          # Add headers to weights and biases
          if "myproject" in line:
              newline = line.replace("myproject", project_name)
  
          # Intel HLS 'streams' need to be passed by reference to top-level entity or declared as global variables
          # Streams cannot be declared inside a function
          # Therefore, layer connections (inputs/outputs) are declared here
          elif (
              "// hls-fpga-machine-learning insert inter-task streams"
              in line
          ):
              newline = line
              if io_type == "io_stream":
                  for layer in model.get_layers():
                      vars = layer.get_variables()
                      for var in vars:
                          def_cpp = var.definition_cpp()
                          if def_cpp is not None:
                              newline += def_cpp + ";\n"
  
          # Instantiate GCC top-level function, to be used during GCC compilation / hls4ml.predict()
          elif (
              "// hls-fpga-machine-learning instantiate GCC top-level"
              in line
          ):
              newline = line
              if io_type == "io_stream":
                  newline += f"void {project_name}(\n"
                  for inp in model_inputs:
                      newline += (
                          indent
                          + f"stream_in<{inp.type.name}> &{inp.name}_stream,\n"
                      )
                  for out in model_outputs:
                      newline += (
                          indent
                          + f"stream_out<{out.type.name}> &{out.name}_stream,\n"
                      )
                  newline = newline[:-2]  # Remove the tailing ',\n'
                  if model_brams:
                      newline += ",\n" + brams_str
                  newline += "\n) {\n"
              if io_type == "io_parallel":
                  newline = f"output_data {project_name}(\n"
                  newline += indent + "input_data inputs"
                  if model_brams:
                      newline += ",\n" + brams_str
                  newline += "\n) {\n"
  
          # Instantiate HLS top-level function, to be used during HLS synthesis
          elif (
              "// hls-fpga-machine-learning instantiate HLS top-level"
              in line
          ):
              newline = line
              if io_type == "io_stream":
                  newline += f"component void {project_name}(\n"
                  for inp in model_inputs:
                      newline += (
                          indent
                          + f"stream_in<{inp.type.name}> &{inp.name}_stream,\n"
                      )
                  for out in model_outputs:
                      newline += (
                          indent
                          + f"stream_out<{out.type.name}> &{out.name}_stream,\n"
                      )
                  newline = newline[:-2]  # Remove the tailing ',\n'\
                  if model_brams:
                      newline += ",\n" + brams_str
                  newline += "\n) {\n"
              if io_type == "io_parallel":
                  newline += f"component output_data {project_name}(\n"
                  newline += indent + "input_data inputs"
                  if model_brams:
                      newline += ",\n" + brams_str
                  newline += "\n) {\n"
  
          # Insert HLS pragmas such as maximum frequency, initiation interval etc.
          elif "// hls-fpga-machine-learning insert cpragmas" in line:
              newline = line
              if io_type == "io_parallel":
                  newline += "hls_max_concurrency(0)\n"
                  newline += f"hls_component_ii({self.get_max_reuse_factor(model)})\n"
              clock_mhz = 1000 / (
                  model.config.get_config_value("ClockPeriod")
              )
              newline += f"hls_scheduler_target_fmax_mhz({np.ceil(clock_mhz).astype(int)})\n"
  
          # In io_parallel, an output (struct) is returned from the top-level function
          # Therefore, it needs to be initialised before returning
          # In io_stream, the input is of type 'stream_in' and output is of type 'stream_out'
          # However, individual layers accept the type 'stream'
          # Therefore, data is first read from 'stream_in', written to 'stream' and propagated through network
          elif (
              "// hls-fpga-machine-learning initialize input/output"
              in line
          ):
              if io_type == "io_stream":
                  newline = line
                  for inp in model_inputs:
                      newline += (
                          indent
                          + f"for (size_t i = 0; i < {inp.size_cpp()} / {inp.type.name}::size; i++) {{\n"
                      )
                      newline += (
                          indent
                          + f"  {inp.type.name} tmp = {inp.name}_stream.read();\n"
                      )
                      newline += indent + f"  {inp.name}.write(tmp);\n"
                      newline += indent + "}\n"
              else:
                  newline = line
                  newline += (
                      indent + "hls_register output_data outputs;\n"
                  )
  
          # Insert weights
          elif "// hls-fpga-machine-learning insert weights" in line:
              newline = line
              for layer in model.get_layers():
                  for w in layer.get_weights():
                      if w not in model_brams:
                          newline += f'#include "weights/{w.name}.h"\n'
  
          # Insert test weights
          elif (
              "// hls-fpga-machine-learning insert test weights" in line
          ):
              newline = line
              for layer in model.get_layers():
                  for w in layer.get_weights():
                      newline += f'#include "weights/{w.name}_test.h"\n'
  
          # Neural net instantiation
          elif "// hls-fpga-machine-learning insert layers" in line:
              newline = line + "\n"
              model_inputs = model.get_input_variables()
              model_outputs = model.get_output_variables()
              for layer in model.get_layers():
                  if io_type != "io_stream":
                      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"
                  func = layer.get_attr("function_cpp", None)
                  if func:
                      newline += "    " + func + "\n"
                      if model.config.trace_output and layer.get_attr(
                          "trace", False
                      ):
                          newline += "#ifndef HLS_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"
  
          # In io_parallel, a return is required; for more details see myproject.cpp & myproject.h
          elif "// hls-fpga-machine-learning return" in line:
              if io_type == "io_stream":
                  newline = line
                  for out in model_outputs:
                      newline += (
                          indent
                          + f"for (size_t i = 0; i < {out.size_cpp()} / {out.type.name}::size; i++) {{\n"
                      )
                      newline += (
                          indent
                          + f"  {out.type.name} tmp = {out.name}.read();\n"
                      )
                      newline += (
                          indent + f"  {out.name}_stream.write(tmp);\n"
                      )
                      newline += indent + "}\n"
                  newline += "}\n"
              else:
                  newline = line
                  newline += indent + "return outputs;\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.backends import get_backend
  from hls4ml.model.layers import Conv1D, Conv2D, Conv2DBatchnorm, Dense
  from hls4ml.utils.fixed_point_utils import FixedPointEmulator, ceil_log2, uint_to_binary
  from hls4ml.writer.writers import Writer
label_desc: Use image node_id 6 for calling the QuartusWriter obj's underlying member method code with example usage: obj.write_project_cpp(model) without return types