def getfilesfromCN(componentNetwork, fpga_component, localmode, inputdir):
    cn = expatbuilder.parse(componentNetwork, False)
    directories = []

    for component in cn.getElementsByTagName('component'):
        if component.getAttribute('name') == fpga_component:
            for implementation in component.getElementsByTagName(
                    'implementation'):
                if implementation.getAttribute('id') == "1":
                    for source_file in implementation.getElementsByTagName(
                            'source'):
                        if source_file.getAttribute('path') not in directories:
                            directories.append(
                                source_file.getAttribute('path'))

    #TODO Not be the best way to get the main component directory.
    firstdir = tmpdir = os.path.join(generated_src_dir, directories[0])

    # Get Files
    for ddir in directories:
        if localmode == True:
            localdir = os.path.abspath(os.path.join(inputdir, ddir))
            tmpdir = os.path.join(generated_src_dir, ddir)
            os.makedirs(tmpdir, exist_ok=True)
            copytree(localdir, tmpdir)
        else:
            repository.set_source(settings.repository_user_dir)
            tmpdir = os.path.join(generated_src_dir, ddir)
            os.makedirs(tmpdir, exist_ok=True)
            repository.downloadFiles(ddir, tmpdir)
            repository.set_source(repository_ipcoregen_source)
    return firstdir
def getfilesfromCN(componentNetwork, fpga_component, localmode, inputdir):
    cn = expatbuilder.parse(componentNetwork, False)
    dirs = []

    for component in cn.getElementsByTagName('component'):
        if component.getAttribute('name') == fpga_component:
            for implementation in component.getElementsByTagName(
                    'implementation'):
                if implementation.getAttribute('id') == "1":
                    for source_file in implementation.getElementsByTagName(
                            'source'):
                        if source_file.getAttribute('path') not in dirs:
                            dirs.append(source_file.getAttribute('path'))

    # Get Files
    for ddir in dirs:
        if localmode == True:
            localdir = os.path.abspath(os.path.join(inputdir, ddir))
            tmpdir = os.path.join(generated_src_dir, ddir)
            os.makedirs(tmpdir, exist_ok=True)
            copytree(localdir, tmpdir)
        else:
            repository.set_source(settings.repository_user_dir)
            tmpdir = os.path.join(generated_src_dir, ddir)
            os.makedirs(tmpdir, exist_ok=True)
            repository.downloadFiles(ddir, tmpdir)
            repository.set_source(repository_ipcoregen_source)

    files = []
    for ddir in dirs:
        for root, directories, filenames in os.walk(tmpdir):
            for filename in filenames:
                if os.path.isfile(os.path.join(tmpdir, filename)):
                    with open(os.path.join(tmpdir, filename), 'r') as file:
                        for line in file:
                            if '#pragma ipcoregen function' in line:
                                function_name = line.replace(
                                    '#pragma ipcoregen function ',
                                    '').split()[0]
                                relpath, filename = os.path.split(
                                    os.path.join(tmpdir, filename))
                                file_funtion = [
                                    os.path.join(tmpdir, filename),
                                    function_name
                                ]
                                files.append(file_funtion)
    return files
def ipcore_generator(componentNetwork, inputdir, outputdir, localmode):
    # Parse Deployment Plan and Component Network
    for fpga_component in getFPGAcomponentsFromCN(componentNetwork):
        CN_files = getfilesfromCN(componentNetwork, fpga_component, localmode,
                                  inputdir)

        for file in CN_files:
            top_function = "{}".format(file[1])
            tmpdir, src_file = os.path.split(file[0])
            src_file = os.path.relpath(os.path.join(tmpdir, src_file),
                                       generated_src_dir)
            header_file = "{}.h".format(os.path.splitext(src_file)[0])

            #timestamp = int(time.time())
            #solution_name = "{}-{}".format(top_function, timestamp)
            solution_name = top_function

            os.makedirs(generated_src_dir, exist_ok=True)

            # Transform source code, generate IP Core and create modified software component
            exitcode = generateIPcore(generated_src_dir, src_file, header_file,
                                      top_function, solution_name)

            if exitcode == 0:
                # ZIP IP Core
                exitcode = os.system(
                    "cd " + generated_ipcore_dir +
                    "/ && zip -r {}.zip {}/ > ../zip.log && cd - > /dev/null".
                    format(solution_name, solution_name))

            if exitcode == 0:
                print(ANSI_GREEN + "\nIP Core Generation Finished" + ANSI_END)

                ipcore_zip = os.path.join(generated_ipcore_dir,
                                          "{}.zip".format(solution_name))
                drivers_dir = os.path.join(generated_ipcore_dir, solution_name,
                                           "impl", "ip", "drivers",
                                           top_function + "_v1_0", "src")
                if not os.path.isdir(drivers_dir):
                    drivers_dir = os.path.join(generated_ipcore_dir,
                                               solution_name, "impl", "ip",
                                               "drivers",
                                               top_function + "_top_v1_0",
                                               "src")
                if not os.path.isdir(drivers_dir):
                    drivers_dir = os.path.join(generated_ipcore_dir,
                                               solution_name, "impl", "ip",
                                               "drivers",
                                               top_function.lower() + "_v1_0",
                                               "src")
                if not os.path.isdir(drivers_dir):
                    drivers_dir = os.path.join(
                        generated_ipcore_dir, solution_name, "impl", "ip",
                        "drivers",
                        top_function.lower() + "_top_v1_0", "src")

                # Add new implementation to Component Network
                files = [tmpdir, drivers_dir, ipcore_zip]
                addfilestoCN(componentNetwork, fpga_component, files,
                             solution_name)

                # Upload to Repository or save locally
                if localmode == True:
                    print(ANSI_CYAN + "\nSaving files to output dir..." +
                          ANSI_END)
                    copy(ipcore_zip, os.path.join(outputdir, solution_name))
                    copytree(generated_src_dir,
                             os.path.join(outputdir, solution_name))
                    copytree(
                        drivers_dir,
                        os.path.join(
                            outputdir, solution_name,
                            os.path.relpath(tmpdir, generated_src_dir),
                            "drivers"))
                    copy(componentNetwork, outputdir)
                else:
                    print(ANSI_CYAN + "\nUploading files to Repository..." +
                          ANSI_END)
                    repository.set_source(repository_ipcoregen_source)
                    repository.uploadIPCoreZip(ipcore_zip, solution_name,
                                               "zip", top_function)
                    repository.uploadDir(generated_src_dir, solution_name,
                                         "cpp")
                    repository.uploadDir(
                        drivers_dir,
                        os.path.join(
                            solution_name,
                            os.path.relpath(tmpdir, generated_src_dir),
                            "drivers"))
                    #repository.set_source(settings.repository_user_dir)
                    repository.uploadFile(componentNetwork,
                                          settings.repository_descriptions_dir,
                                          "componentnetwork")

                print(ANSI_GREEN + "\nFinished" + ANSI_END)
            else:
                print(ANSI_RED +
                      "\nIP Core Generation Failed - exitcode: {}".format(
                          exitcode) + ANSI_END)

    # Delete Temporary Files
    if clean_temp:
        if os.path.isdir(generated_ipcore_dir):
            shutil.rmtree(generated_ipcore_dir)
        if os.path.isdir(generated_src_dir):
            shutil.rmtree(generated_src_dir)
        if os.path.isdir(tempdir):
            shutil.rmtree(tempdir)
        os.mkdir(tempdir)
def subscribe(repository_projectname, path, tempdir):
    """
	Subscribe to a project using the Application Manager. Waits for updates to the project and
	analyses any checked deployments continually.
	"""
    print(ANSI_GREEN +
          "Subscribing to project {}. Waiting for updates...".format(
              repository_projectname) + ANSI_END)

    try:
        ws = websocket.create_connection("ws://{}:{}".format(
            settings.app_manager_ip, settings.app_manager_port))
        req = "{{\"user\":\"{}\" , \"project\":\"{}\"}}".format(
            settings.repository_user, repository_projectname)
        ws.send(req)
        result = ws.recv()
    except ConnectionRefusedError:
        print(ANSI_RED + "Cannot connect to Application Manager." + ANSI_END)
        print("Response: {}".format(result)) if 'result' in locals() else None
        sys.exit(1)

    try:
        reply = json.loads(result)
        if not 'suscribed_to_project' in reply:
            raise json.decoder.JSONDecodeError
    except json.decoder.JSONDecodeError:
        print(ANSI_RED +
              "Invalid response from Application Manager. Response: {}".format(
                  result))
        sys.exit(1)

    repository.websocketUpdateStatus(repository_projectname,
                                     "ip_core_generator", "waiting")

    while True:
        try:
            result = ws.recv()
            reply = json.loads(result)

            if 'project' in reply and reply[
                    'project'] == repository_projectname:
                if 'pt_code_analysis' in reply and 'status' in reply[
                        'pt_code_analysis']:
                    if reply['pt_code_analysis']['status'] == 'finished':
                        print(
                            "PT Code Analysis finished - Starting IP Core Generator\n"
                        )
                        repository.websocketUpdateStatus(
                            repository_projectname, "ip_core_generator",
                            "started")
                        repository.set_project(sys.argv[2])
                        repository.set_source(settings.repository_pt_dir)
                        repository.downloadFiles(
                            settings.repository_descriptions_dir, tempdir)
                        local_mode(tempdir, tempdir, False)
                        repository.websocketUpdateStatus(
                            repository_projectname, "ip_core_generator",
                            "finished")
                        print("Exiting IP Core Generator")
                        sys.exit(0)

        except json.decoder.JSONDecodeError:
            print(ANSI_RED +
                  "Invalid response from Application Manager. Response: {}".
                  format(result))
            sys.exit(1)
def main():

    #Remove temporary directories
    if clean_temp:
        if os.path.isdir(generated_ipcore_dir):
            shutil.rmtree(generated_ipcore_dir)
        if os.path.isdir(generated_src_dir):
            shutil.rmtree(generated_src_dir)
        if os.path.isdir(tempdir):
            shutil.rmtree(tempdir)
    if not os.path.isdir(tempdir):
        os.mkdir(tempdir)

    # Usage
    if len(sys.argv) < 2:
        print("Usage: {} [mode] <args for mode>".format(sys.argv[0]))
        print(
            "Valid modes are: subscribe, remote, local, source, upload, download, verify, listdeps, clean"
        )
        sys.exit(1)

    # Subscribe
    elif sys.argv[1] == 'subscribe':
        """
		Subscribe to a project using the Application Manager. Waits for updates to the project and
		analyses any checked deployments continually.
		Arguments:
			[2] - project name to subscribe to
		"""
        if len(sys.argv) < 3:
            print("Usage: {} subscribe <model-name>".format(sys.argv[0]))
            sys.exit(1)

        repository.set_project(sys.argv[2])
        repository.set_source(settings.repository_user_dir)
        subscribe(sys.argv[2], settings.repository_descriptions_dir, tempdir)

    # Remote
    elif sys.argv[1] == 'remote':
        """
		Download all files from the repository found in a given path, then perform analysis on it.
		Arguments:
			[2] - repository path to the file to download (including filename)
		"""
        if len(sys.argv) < 3:
            print("Usage: {} remote <project-name>".format(sys.argv[0]))
            sys.exit(1)

        repository.set_project(sys.argv[2])
        repository.set_source(settings.repository_pt_dir)
        repository.downloadFiles(settings.repository_descriptions_dir, tempdir)
        local_mode(tempdir, tempdir, False)

    # Local
    elif sys.argv[1] == 'local':
        """
		Analyse a folder of XML files.
		Arguments:
			[2] - path to folder to analyse
			[3] - path to folder to write outputs to
		"""
        if len(sys.argv) < 4:
            print("Usage: {} local <input-model-dir> <output-dir>".format(
                sys.argv[0]))
            sys.exit(1)
        inputdir = repository.enforce_trailing_slash(sys.argv[2])
        outputdir = repository.enforce_trailing_slash(sys.argv[3])
        copytree(inputdir, tempdir)
        local_mode(tempdir, outputdir, True)

    # Source
    elif sys.argv[1] == 'source':
        """
		Run the IP Core Generator on local source files
		Arguments:
			[2] - source filename
			[3] - header filename
			[4] - top function name
			[5] - output directory
		"""
        if len(sys.argv) < 6:
            print(
                "Usage: {} source <source-file> <header-file> <top-funtion> <output-dir>"
                .format(sys.argv[0]))
            sys.exit(1)
        srcdir = repository.enforce_trailing_slash(
            os.path.relpath(os.path.dirname(sys.argv[2])))
        outputdir = repository.enforce_trailing_slash(
            os.path.relpath(sys.argv[5]))
        source_mode(srcdir, os.path.basename(sys.argv[2]),
                    os.path.basename(sys.argv[3]), sys.argv[4], sys.argv[4],
                    outputdir)

    # Upload
    elif sys.argv[1] == 'upload':
        """
		Upload a file to the Repository.
		Arguments:
			[2] - path to the file to upload
			[3] - project name in the repository
			[4] - repository source name
			[5] - path in the repository to upload to (including filename)
			[6] - what to set the "data_type" metadata to
			[7] - what to set the "checked" metadata to
		"""
        if len(sys.argv) < 6:
            print(
                "Usage: {} upload <source-file> <project-name> <source-name> <destpath> <data-type> <checked>"
                .format(sys.argv[0]))
            sys.exit(1)

        repository.set_project(sys.argv[3])
        repository.set_source(sys.argv[4])
        repository.uploadFile(sys.argv[2], sys.argv[5], sys.argv[6],
                              sys.argv[7])
        print("Upload complete.")

    # Download
    elif sys.argv[1] == 'download':
        """
		Download a file from the Repository.
		Arguments:
			[2] - project name in the repository
			[3] - repository source name
			[4] - path to the file to download (including filename)
			[5] - local path (including filename) to save the file as
		"""
        if len(sys.argv) < 4:
            print(
                "Usage: {} download <project-name> <source-name> <file> <output-file>"
                .format(sys.argv[0]))
            sys.exit(1)

        repository.set_project(sys.argv[2])
        repository.set_source(sys.argv[3])
        repository.downloadFile(sys.argv[4], sys.argv[5])
        print("Download complete.")

    # Verify
    elif sys.argv[1] == 'verify':
        """
		Check if we can see the other tools.
		"""
        rc = subprocess.call(['which', 'vivado_hls'], stdout=subprocess.PIPE)
        if rc == 0:
            print('Xilinx tools - OK')
        else:
            print(ANSI_RED + 'Missing Xilinx tools!' + ANSI_END)
            print('Please check if Vivado is installed and accessible.')
            sys.exit(1)

        repository.authenticate()
        print('Repository is assessible - OK')

        print("All Dependencies tests passed.")
        sys.exit(0)

    # List Deployments
    elif sys.argv[1] == 'listdeps':
        """
		List all deployments in the given path.
		Arguments:
			[2] - project name in the repository to search for deployments
		"""

        repository.set_project(sys.argv[2])
        repository.set_source(settings.repository_user_dir)
        repository.listDeployments(settings.repository_descriptions_dir)

    # Clean
    elif sys.argv[1] == 'clean':
        """
		Deletes temporary files and folders
		"""
        if os.path.isdir(tempdir):
            shutil.rmtree(tempdir)
        if os.path.isdir(generated_ipcore_dir):
            shutil.rmtree(generated_ipcore_dir)
        if os.path.isdir(generated_src_dir):
            shutil.rmtree(generated_src_dir)
        if os.path.isdir('__pycache__'):
            shutil.rmtree('__pycache__')

    else:
        print("Invalid mode.")
        print(
            "Valid modes are: subscribe, remote, local, source, upload, download, verify, listdeps, clean"
        )
        sys.exit(1)

    # Delete temporary files on exit
    if clean_temp:
        if os.path.isdir(tempdir):
            shutil.rmtree(tempdir)