Skip to content

Commit

Permalink
Add vitis rules for HLS.
Browse files Browse the repository at this point in the history
  • Loading branch information
Stephen Tridgell authored and stridge-cruxml committed Feb 1, 2023
1 parent ec601eb commit 33e3786
Show file tree
Hide file tree
Showing 295 changed files with 293,968 additions and 0 deletions.
21 changes: 21 additions & 0 deletions vitis/BUILD
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
exports_files(["vitis_generate.tcl.template"])

# Define versions of vitis_hls/vivado_hls as needed.
# These are copied from the installation.
cc_library(
name = "v2021_2_cc",
srcs = glob([
"v2021_2/**/*.h",
]),
strip_include_prefix = "external/rules_hdl/",
visibility = ["//visibility:public"],
)

cc_library(
name = "v2020_1_cc",
srcs = glob([
"v2020_1/**/*.h",
]),
strip_include_prefix = "external/rules_hdl/",
visibility = ["//visibility:public"],
)
113 changes: 113 additions & 0 deletions vitis/defs.bzl
Original file line number Diff line number Diff line change
@@ -0,0 +1,113 @@
"""Defs for generating verilog using HLS"""

HlsFileInfo = provider(
"HLS files required by vitis",
fields = {
"files": "a list of files",
},
)

def _vitis_hls_files_aspect_impl(target, ctx):
"""Filter out the vitis header deps."""
files = []

for f in target[CcInfo].compilation_context.headers.to_list():
if "vitis/v" not in f.dirname:
files.append(f)

if hasattr(ctx.rule.attr, "srcs"):
for src in ctx.rule.attr.srcs:
for f in src.files.to_list():
if f not in files and "vitis/v" not in f.dirname:
files.append(f)

if hasattr(ctx.rule.attr, "deps"):
for dep in ctx.rule.attr.deps:
files = files + dep[HlsFileInfo].files

return [HlsFileInfo(files = files)]

vitis_hls_files_aspect = aspect(
implementation = _vitis_hls_files_aspect_impl,
attr_aspects = ["deps"],
)

def _vitis_generate_impl(ctx):
all_files = []
cflags = "-D__SYNTHESIS__=1 --std=c++17"
for dep in ctx.attr.deps:
for file in dep[HlsFileInfo].files:
external_path = "/".join([file.root.path, file.owner.workspace_root]) if file.root.path else file.owner.workspace_root
cflags += " -I" + external_path

source_file_str = ""
for dep in ctx.attr.deps:
for file in dep[HlsFileInfo].files:
all_files.append(file)
source_file_str += "add_file " + file.path + " -cflags \"" + cflags + "\"\n"

vitis_tcl = ctx.actions.declare_file("{}_run_hls.tcl".format(ctx.label.name))
vitis_log = ctx.actions.declare_file("{}_hls.log".format(ctx.label.name))

substitutions = {
"{{PROJECT_NAME}}": ctx.label.name,
"{{SOURCE_FILES}}": source_file_str,
"{{TOP_LEVEL_FUNCTION}}": ctx.attr.top_func,
"{{PART_NUMBER}}": ctx.attr.part_number,
"{{CLOCK_PERIOD}}": ctx.attr.clock_period,
}

ctx.actions.expand_template(
template = ctx.file._vitis_generate_template,
output = vitis_tcl,
substitutions = substitutions,
)

vitis_command = "source " + ctx.file.xilinx_env.path + " && "
if ctx.attr.use_vivado_hls:
vitis_command += "vivado_hls " + vitis_tcl.path
else:
vitis_command += "vitis_hls " + vitis_tcl.path
vitis_command += " -l " + vitis_log.path
vitis_command += " && tar -czvf " + ctx.outputs.out.path + " -C "
vitis_command += ctx.label.name + "/sol1/impl/verilog ."

outputs = [vitis_log, ctx.outputs.out]

if ctx.attr.use_vivado_hls:
progress_message = "Running with vivado_hls: {}".format(ctx.label.name)
else:
progress_message = "Running with vitis_hls: {}".format(ctx.label.name)

ctx.actions.run_shell(
outputs = outputs,
inputs = all_files + [vitis_tcl, ctx.file.xilinx_env],
progress_message = progress_message,
command = vitis_command,
)

return [
DefaultInfo(files = depset(outputs)),
]

vitis_generate = rule(
implementation = _vitis_generate_impl,
attrs = {
"top_func": attr.string(doc = "The name of the top level function.", mandatory = True),
"clock_period": attr.string(doc = "The clock period for the module.", mandatory = True),
"part_number": attr.string(doc = "The part number to use. Default is ZCU111", default = "xczu28dr-ffvg1517-2-e"),
"deps": attr.label_list(doc = "The file to generate from", aspects = [vitis_hls_files_aspect], mandatory = True),
"out": attr.output(doc = "The generated verilog files", mandatory = True),
"use_vivado_hls": attr.bool(doc = "Use vivado HLS instead of vitis hls.", default = False),
"_vitis_generate_template": attr.label(
doc = "The tcl template to run with vitis.",
default = "@rules_hdl//vitis:vitis_generate.tcl.template",
allow_single_file = [".template"],
),
"xilinx_env": attr.label(
doc = "Environment variables for xilinx tools.",
allow_single_file = [".sh"],
mandatory = True,
),
},
)
90 changes: 90 additions & 0 deletions vitis/tests/BUILD
Original file line number Diff line number Diff line change
@@ -0,0 +1,90 @@
load("//vitis:defs.bzl", "vitis_generate")

# This is to test the path of generated headers.
genrule(
name = "consts",
outs = [
"consts.h",
],
cmd_bash = "touch $(OUTS)",
)

cc_library(
name = "consts_cc",
hdrs = [
"consts.h",
],
)

cc_library(
name = "hls_adder",
srcs = [
"hls_adder.cc",
],
hdrs = [
"hls_adder.h",
],
deps = [
"consts_cc",
"@rules_hdl//vitis:v2021_2_cc",
],
)

cc_test(
name = "hls_adder_test",
srcs = [
"hls_adder_test.cc",
],
deps = [
":hls_adder",
"@com_google_googletest//:gtest_main",
],
)

cc_library(
name = "hls_adder_vivado",
srcs = [
"hls_adder.cc",
],
hdrs = [
"hls_adder.h",
],
defines = ["WITH_VIVADO_HLS=1"],
deps = [
"consts_cc",
"@rules_hdl//vitis:v2020_1_cc",
],
)

cc_test(
name = "hls_adder_vivado_test",
srcs = [
"hls_adder_test.cc",
],
deps = [
":hls_adder_vivado",
"@com_google_googletest//:gtest_main",
],
)

vitis_generate(
name = "adder",
out = "adder.tar.gz",
clock_period = "10.0",
tags = ["manual"],
top_func = "adder",
xilinx_env = ":xilinx_env.sh",
deps = [":hls_adder"],
)

vitis_generate(
name = "adder_vivado",
out = "adder_vivado.tar.gz",
clock_period = "10.0",
tags = ["manual"],
# Note need namespace with vivado_hls.
top_func = "vitis::adder",
use_vivado_hls = True,
xilinx_env = ":xilinx_env_vivado.sh",
deps = [":hls_adder_vivado"],
)
10 changes: 10 additions & 0 deletions vitis/tests/hls_adder.cc
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
#include "hls_adder.h"

namespace vitis {

void adder(fixed &a, fixed &b, fixed &c) {
#pragma HLS pipeline II = 1
c = a + b;
}

} // namespace vitis
19 changes: 19 additions & 0 deletions vitis/tests/hls_adder.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@

#ifdef __SYNTHESIS__
#include <ap_fixed.h>
#else
#ifdef WITH_VIVADO_HLS
#include "vitis/v2020_1/ap_fixed.h"
#else
#include "vitis/v2021_2/ap_fixed.h"
#endif
#endif

#include "vitis/tests/consts.h"
namespace vitis {

typedef ap_fixed<16, 9> fixed;

void adder(fixed &a, fixed &b, fixed &c);

} // namespace vitis
27 changes: 27 additions & 0 deletions vitis/tests/hls_adder_test.cc
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
#include "hls_adder.h"

#include "gtest/gtest.h"

namespace vitis {
namespace {

class HlsAdderTest : public testing::Test {};

TEST_F(HlsAdderTest, one_plus_one) {
fixed a = 1;
fixed b = 1;
fixed c;
adder(a, b, c);
EXPECT_EQ(c, 2);
}

TEST_F(HlsAdderTest, quarter_plus_quarter) {
fixed a = 0.25;
fixed b = 0.25;
fixed c;
adder(a, b, c);
EXPECT_EQ(c, 0.5);
}

} // namespace
} // namespace vitis
5 changes: 5 additions & 0 deletions vitis/tests/xilinx_env.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
#! /bin/bash

export HOME=/tmp
source /opt/xilinx/Vitis_HLS/2021.2/settings64.sh
export XILINXD_LICENSE_FILE=2100@localhost
5 changes: 5 additions & 0 deletions vitis/tests/xilinx_env_vivado.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
#! /bin/bash

export HOME=/tmp
source /opt/xilinx/Vivado/2020.1/settings64.sh
export XILINXD_LICENSE_FILE=2100@localhost
Loading

0 comments on commit 33e3786

Please sign in to comment.