Skip to content

Commit

Permalink
Merge branch 'release-1.0.0.a1'
Browse files Browse the repository at this point in the history
Merge in all changes to date from development branch using release-1.0.0.a1 branch."
  • Loading branch information
benjmarshall committed Jun 21, 2017
2 parents e39c6d8 + f6abf35 commit 371abc6
Show file tree
Hide file tree
Showing 16 changed files with 631 additions and 241 deletions.
151 changes: 116 additions & 35 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,26 +1,31 @@
# Vivado HLS Command Line Tool (hlsclt)

A Vivado HLS Command Line Helper Tool.

Current functionality includes flexibly executing the main Vivado HLS build stages and cleaning up generated files. Supports a command line driven development process.
Supports a command line driven development process, which increases the performance of the HLS tool and aids compatibility with source control tools, in order achieve an increase in productivity.

## Features
- Flexibly execute any of the Vivado HLS build stages
- Open build reports
- Clean up generated files
- View complete project status
- Open Vivado HLS GUI with project loaded

## Requirements
Python 3 - tested with python 3.6.1
- Python 2 or 3
- Tested with and 2.7.5 and 3.6.1
- Vivado HLS
- Tested with Vivado HLS 2017.1

## Install
Easy installation:
```Shell
pip install hlsclt
```

Manual installation:
```Shell
git clone https://github.com/benjmarshall/hlsclt.git
sudo cp ./hlsclt/hlsclt/hlsclt.py /usr/local/bin/hlsclt
sudo chmod +x /usr/local.bin/hlsclt
```
Depends on [Click](https://pypi.python.org/pypi/click) which will be installed automatically by pip.

## Usage
This tool is intended to aid command line driven development process for Vivado HLS. Whilst the tool is designed to be flexible, certain guidelines should be followed. A top level project folder should contain your HLS source files (or folders) and a 'hls_config.py' file which specifies some of the required configuration for a HLS project (device, clock speed etc).
### Quickstart
This tool is intended to aid a command line driven development process for Vivado HLS. Whilst the tool is designed to be flexible, certain guidelines should be followed. A top level project folder should contain your HLS source files (or folders) and a 'hls_config.py' file which specifies some of the required configuration for a HLS project (device, clock speed etc).

A recommended directory structure is as follows:

Expand All @@ -32,42 +37,118 @@ A recommended directory structure is as follows:
- testbench.cpp
- hls_config.py

An example project structure and hls_config.py can be found in the [examples](hlsclt/examples) directory.
An example project structure and hls_config.py can be found in the [examples](hlsclt/examples) directory. A full guide for setting a config.py can be seen in the [Project Config](#project-configuration) section.

The tool should be invoked from within the project folder, i.e.:
The tool should be invoked from within the project folder, i.e. :
```Shell
cd my_project_name
hlsclt -csim
hlsclt build csim
```

The tool will read in the configuration from your 'hls_config.py' file and invoke Vivado HLS to perform the chosen build stages.

All of the tool options can be seen my using the '--help' argument:
All of the tools commands and options can be seen by using the '--help' argument:

```
[ben@localhost]$ hlsclt --help
usage: hlsclt [-h] [-clean] [-keep] [-csim] [-syn] [-cosim | -cosim_debug] [-export_ip | -evaluate_ip]
[-export_dsp | -evaluate_dsp]
Helper tool for using Vivado HLS through the command line. If no arguments are specified then a default
run is executed which includes C simulation, C synthesis, Cosimulation and export for both Vivado IP
Catalog and System Generator. If any of the run options are specified then only those specified are
performed.
optional arguments:
-h, --help show this help message and exit
-clean remove all Vivado HLS generated files
-keep keep all previous solution and generate a new one
-csim perform C simulation stage
-syn perform C synthesis stage
-cosim perform cosimulation
-cosim_debug perform cosimulation with debug logging
-export_ip perform export for Vivado IP Catalog
-evaluate_ip perform export for Vivado IP Catalog with build to place and route
-export_dsp perform export for System Generator
-evaluate_dsp perform export for System Generator with build to place and route
Usage: hlsclt [OPTIONS] COMMAND [ARGS]...
Helper tool for using Vivado HLS through the command line. If no arguments
are specified then a default run is executed which includes C simulation,
C synthesis, Cosimulation and export for both Vivado IP Catalog and System
Generator. If any of the run options are specified then only those
specified are performed.
Options:
--version Show the version and exit.
--help Show this message and exit.
Commands:
build Run HLS build stages.
clean Remove generated files.
open_gui Open the Vivado HLS GUI and load the project.
report Open reports.
status Print out the current project status.
```

### Nested Commands
The tool is built using the concept of 'nested' commands (like git for example), where the main command 'hlsclt' has a group of subcommands, some of which in turn have subcommands. The 'status' command is a simple example of single level of nesting:

```
[ben@localhost]$ hlsclt status
Project Details
Project Name: proj_simple_adder
Number of solutions generated: 1
Latest Solution Folder: 'proj_simple_adder/solution1'
Language Choice: vhdl
Build Status
C Simulation: Pass
C Synthesis: Not Run
Cosimulation: Not Run
Export:
IP Catalog: Not Run
System Generator: Not Run
Export Evaluation: Not Run
```

The build subcommand is slightly more complex than the other top-level commands. Nested subcommands under the build command can be chained in order to perform multiple HLS build stages, each with their own options:

```
[ben@localhost]$ hlsclt build csim syn cosim -d
```

In this example the tool will launch the HLS process to run a C simulation, followed by C Synthesis, and finally a cosimulation with debugging enabled so that we can view the waveforms of the cosimulation at a later point.

Each command or subcommand has it's own help option which gives specific information about the command and how to use it. For example the export subcomand:
```
[ben@localhost]$ hlsclt build export --help
Usage: hlsclt build export [OPTIONS]
Runs the Vivado HLS export stage.
Options:
-t, --type [ip|sysgen] Specify an export type, Vivado IP Catalog or System
Generator. Accepts multiple occurrences. [required]
-e, --evaluate Runs Vivado synthesis and place and route for the
generated export.
--help Show this message and exit.
```

### Project Configuration
Each Vivado HLS project requires a 'config.py' file in order to use hlsclt. This file contains all of the information required by Vivado HLS and hlsclt to perform build operations for your project. The file uses basic python syntax to specify the configuration in a parsable format. The full list of available configuration options is shown below:

|Configuration Item | Variable Name | Valid Options | Required |
|-------------------|-----------------------|--------------------------------|----------|
|Project Name |project_name |Any valid directory name |No (Default is name of the containing project folder prepended with 'proj_') |
|Function Name |top_level_function_name|String which match function name|Yes |
|Source Files Dir |src_dir_name |Name of directory where source files are located, relative to the project folder|No (Default is 'src')|
|Testbench Files Dir|tb_dir_name |Name of directory where testbench files are located, relative to the project folder|No (Default is 'tb')|
|Source Files |src_files |A list of source files required, located within the Source Files directory|Yes|
|Testbench Files |tb_files |A list of testbench files required, located within the Testbench Files directory|Yes|
|Device String |part_name |A device string as used by Vivado HLS (see examples)|Yes|
|Clock Period |clock_period |A value in nanoseconds input as a string, e.g. "10"|Yes|
|HDL Language |language |Either "vhdl" or "verilog" |No (Default is "vhdl")|


Here is an example file taken from the [simple_adder](hlsclt/examples/simple_adder) example shipped with the tool (note that some of the optional items have been commented out in order to use the defaults):

```python
# Config file for Simple Adder Vivado HLS project

#project_name = "optional_project_name_here"
top_level_function_name = "simple_adder"
#src_dir_name = "src"
#tb_dir_name = "tb"
src_files = ["dut.h","dut.cpp"]
tb_files = ["testbench.cpp"]
part_name = "xc7z020clg484-1"
clock_period = "10"
language = "vhdl"
```

## License

See [LICENSE](LICENSE)

## Bugs/Issues
If you have any issues or find a bug please first search the [open issues](https://github.com/benjmarshall/hlsclt/issues) on github and then submit a new issue ticket.
1 change: 0 additions & 1 deletion hlsclt/__init__.py
Original file line number Diff line number Diff line change
@@ -1,2 +1 @@
# __init__.py
__version__ = '1.0.0.dev2'
1 change: 1 addition & 0 deletions hlsclt/_version.py
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
__version__ = '1.0.0.a1'
Empty file.
183 changes: 183 additions & 0 deletions hlsclt/build_commands/build_commands.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,183 @@
# -*- coding: utf-8 -*-
""" Build related subcommands for HLSCLT.
Copyright (c) 2017 Ben Marshall
"""

### Imports ###
import click
import os
import subprocess
from hlsclt.helper_funcs import find_solution_num
from hlsclt.report_commands.report_commands import open_report

### Supporting Functions ###
# Function to generate the 'pre-amble' within the HLS Tcl build script.
def do_start_build_stuff(ctx):
config = ctx.obj.config
solution_num = ctx.obj.solution_num
try:
file = click.open_file("run_hls.tcl","w")
file.write("open_project " + config["project_name"] + "\n")
file.write("set_top " + config["top_level_function_name"] + "\n")
for src_file in config["src_files"]:
file.write("add_files " + config["src_dir_name"] + "/" + src_file + "\n")
for tb_file in config["tb_files"]:
file.write("add_files -tb " + config["tb_dir_name"] + "/" + tb_file + "\n")
if ctx.params['keep']:
file.write("open_solution -reset \"solution" + str(solution_num) + "\"" + "\n")
else:
file.write("open_solution \"solution" + str(solution_num) + "\"" + "\n")
file.write("set_part \{" + config["part_name"] + "\}" + "\n")
file.write("create_clock -period " + config["clock_period"] + " -name default" + "\n")
return file
except OSError:
click.echo("Woah! Couldn't create a Tcl run file in the current folder!")
raise click.Abort()

# Function to write a default build into the HLS Tcl build script.
def do_default_build(ctx):
config = ctx.obj.config
file = ctx.obj.file
file.write("csim_design -clean" + "\n")
file.write("csynth_design" + "\n")
file.write("cosim_design -O -rtl " + config["language"] + "\n")
file.write("export_design -format ip_catalog" + "\n")
file.write("export_design -format sysgen" + "\n")

# Function which defines the main actions of the 'csim' command.
def do_csim_stuff(ctx):
file = ctx.obj.file
file.write("csim_design -clean" + "\n")

# Function which defines the main actions of the 'syn' command.
def do_syn_stuff(ctx):
file = ctx.obj.file
file.write("csynth_design" + "\n")

# Function to perform a search for existing c synthesis results in a specified hls project and solution.
def check_for_syn_results(proj_name, solution_num, top_level_function_name):
return_val = False
try:
with click.open_file(proj_name + "/solution" + str(solution_num) + "/syn/report/" + top_level_function_name + "_csynth.rpt"):
return_val = True
except OSError:
pass
return return_val

# Function to check is C synthesis is going to be required but may have been forgorgotten by the user.
def syn_lookahead_check(ctx):
config = ctx.obj.config
solution_num = ctx.obj.solution_num
file = ctx.obj.file
if (not ctx.obj.syn_command_present) and (not check_for_syn_results(config["project_name"], solution_num, config["top_level_function_name"])):
if click.confirm("C Synthesis has not yet been run but is required for the process(es) you have selected.\nWould you like to add it to this run?", default=True):
click.echo("Adding csynth option.")
file.write("csynth_design" + "\n")
else:
click.echo("Ok, watch out for missing synthesis errors!")

# Function which defines the main actions of the 'cosim' command.
def do_cosim_stuff(ctx,debug):
config = ctx.obj.config
file = ctx.obj.file
if debug:
file.write("cosim_design -rtl " + config["language"] + " -trace_level all" + "\n")
else:
file.write("cosim_design -O -rtl " + config["language"] + "\n")

# Function which defines the main actions of the 'export' command.
def do_export_stuff(ctx,type,evaluate):
config = ctx.obj.config
file = ctx.obj.file
if evaluate:
if "ip" in type:
file.write("export_design -format ip_catalog -evaluate " + config["language"] + "\n")
if "sysgen" in type:
file.write("export_design -format sysgen -evaluate " + config["language"] + "\n")
else:
if "ip" in type:
file.write("export_design -format ip_catalog" + "\n")
if "sysgen" in type:
file.write("export_design -format sysgen" + "\n")

# Function which defines the actions that occur after a HLS build.
def do_end_build_stuff(ctx,sub_command_returns,report):
# Check for reporting flag
if report:
if not sub_command_returns:
# Must be on the default run, add all stages manually
sub_command_returns = ['csim','syn','cosim','export']
for report in sub_command_returns:
open_report(ctx,report)

### Click Command Definitions ###
# Build group entry point
@click.group(chain=True, invoke_without_command=True, short_help='Run HLS build stages.')
@click.option('-k','--keep', is_flag=True, help='Preserves existing solutions and creates a new one.')
@click.option('-r','--report', is_flag=True, help='Open build reports when finished.')
@click.pass_context
def build(ctx,keep,report):
"""Runs the Vivado HLS tool and executes the specified build stages."""
ctx.obj.solution_num = find_solution_num(ctx)
ctx.obj.file = do_start_build_stuff(ctx)
pass

# Callback which executes when all specified build subcommands have been finished.
@build.resultcallback()
@click.pass_context
def build_end_callback(ctx,sub_command_returns,keep,report):
# Catch the case where no subcommands have been issued and offer a default build
if not sub_command_returns:
if click.confirm("No build stages specified, would you like to run a default sequence using all the build stages?", abort=True):
do_default_build(ctx)
ctx.obj.file.write("exit" + "\n")
ctx.obj.file.close()
# Call the Vivado HLS process
hls_processs = subprocess.run(["vivado_hls", "-f", "run_hls.tcl"])
# Check return status of the HLS process.
if hls_processs.returncode < 0:
raise click.Abort()
elif hls_processs.returncode > 0:
click.echo("Warning: HLS Process returned an error, skipping report opening!")
raise click.Abort()
else:
do_end_build_stuff(ctx,sub_command_returns,report)

# csim subcommand
@build.command('csim')
@click.pass_context
def csim(ctx):
"""Runs the Vivado HLS C simulation stage."""
do_csim_stuff(ctx)
return 'csim'

# syn subcommand
@build.command('syn')
@click.pass_context
def syn(ctx):
"""Runs the Vivado HLS C synthesis stage."""
do_syn_stuff(ctx)
ctx.obj.syn_command_present = True
return 'syn'

# cosim subcommand
@build.command('cosim')
@click.option('-d', '--debug', is_flag=True, help='Turns off compile optimisations and enables logging for cosim.')
@click.pass_context
def cosim(ctx,debug):
"""Runs the Vivado HLS cosimulation stage."""
syn_lookahead_check(ctx)
do_cosim_stuff(ctx,debug)
return 'cosim'

# export subcommand
@build.command('export')
@click.option('-t', '--type', required=True, multiple=True, type=click.Choice(['ip','sysgen']), help='Specify an export type, Vivado IP Catalog or System Generator. Accepts multiple occurences.')
@click.option('-e', '--evaluate', is_flag=True, help='Runs Vivado synthesis and place and route for the generated export.')
@click.pass_context
def export(ctx, type, evaluate):
"""Runs the Vivado HLS export stage."""
syn_lookahead_check(ctx)
do_export_stuff(ctx,type,evaluate)
return 'export'
Loading

0 comments on commit 371abc6

Please sign in to comment.