|
| 1 | +"""Defs for generating verilog using HLS""" |
| 2 | + |
| 3 | +HlsFileInfo = provider( |
| 4 | + "HLS files required by vitis", |
| 5 | + fields = { |
| 6 | + "files": "a list of files", |
| 7 | + }, |
| 8 | +) |
| 9 | + |
| 10 | +def _vitis_hls_files_aspect_impl(target, ctx): |
| 11 | + """Filter out the vitis header deps.""" |
| 12 | + files = [] |
| 13 | + |
| 14 | + for f in target[CcInfo].compilation_context.headers.to_list(): |
| 15 | + if "vitis/v" not in f.dirname: |
| 16 | + files.append(f) |
| 17 | + |
| 18 | + if hasattr(ctx.rule.attr, "srcs"): |
| 19 | + for src in ctx.rule.attr.srcs: |
| 20 | + for f in src.files.to_list(): |
| 21 | + if f not in files and "vitis/v" not in f.dirname: |
| 22 | + files.append(f) |
| 23 | + |
| 24 | + if hasattr(ctx.rule.attr, "deps"): |
| 25 | + for dep in ctx.rule.attr.deps: |
| 26 | + files = files + dep[HlsFileInfo].files |
| 27 | + |
| 28 | + return [HlsFileInfo(files = files)] |
| 29 | + |
| 30 | +vitis_hls_files_aspect = aspect( |
| 31 | + implementation = _vitis_hls_files_aspect_impl, |
| 32 | + attr_aspects = ["deps"], |
| 33 | +) |
| 34 | + |
| 35 | +def _vitis_generate_impl(ctx): |
| 36 | + all_files = [] |
| 37 | + cflags = "-D__SYNTHESIS__=1 --std=c++17" |
| 38 | + for dep in ctx.attr.deps: |
| 39 | + for file in dep[HlsFileInfo].files: |
| 40 | + external_path = "/".join([file.root.path, file.owner.workspace_root]) if file.root.path else file.owner.workspace_root |
| 41 | + cflags += " -I" + external_path |
| 42 | + |
| 43 | + source_file_str = "" |
| 44 | + for dep in ctx.attr.deps: |
| 45 | + for file in dep[HlsFileInfo].files: |
| 46 | + all_files.append(file) |
| 47 | + source_file_str += "add_file " + file.path + " -cflags \"" + cflags + "\"\n" |
| 48 | + |
| 49 | + vitis_tcl = ctx.actions.declare_file("{}_run_hls.tcl".format(ctx.label.name)) |
| 50 | + vitis_log = ctx.actions.declare_file("{}_hls.log".format(ctx.label.name)) |
| 51 | + |
| 52 | + substitutions = { |
| 53 | + "{{PROJECT_NAME}}": ctx.label.name, |
| 54 | + "{{SOURCE_FILES}}": source_file_str, |
| 55 | + "{{TOP_LEVEL_FUNCTION}}": ctx.attr.top_func, |
| 56 | + "{{PART_NUMBER}}": ctx.attr.part_number, |
| 57 | + "{{CLOCK_PERIOD}}": ctx.attr.clock_period, |
| 58 | + } |
| 59 | + |
| 60 | + ctx.actions.expand_template( |
| 61 | + template = ctx.file._vitis_generate_template, |
| 62 | + output = vitis_tcl, |
| 63 | + substitutions = substitutions, |
| 64 | + ) |
| 65 | + |
| 66 | + vitis_command = "source " + ctx.file.xilinx_env.path + " && " |
| 67 | + if ctx.attr.use_vivado_hls: |
| 68 | + vitis_command += "vivado_hls " + vitis_tcl.path |
| 69 | + else: |
| 70 | + vitis_command += "vitis_hls " + vitis_tcl.path |
| 71 | + vitis_command += " -l " + vitis_log.path |
| 72 | + vitis_command += " && tar -czvf " + ctx.outputs.out.path + " -C " |
| 73 | + vitis_command += ctx.label.name + "/sol1/impl/verilog ." |
| 74 | + |
| 75 | + outputs = [vitis_log, ctx.outputs.out] |
| 76 | + |
| 77 | + if ctx.attr.use_vivado_hls: |
| 78 | + progress_message = "Running with vivado_hls: {}".format(ctx.label.name) |
| 79 | + else: |
| 80 | + progress_message = "Running with vitis_hls: {}".format(ctx.label.name) |
| 81 | + |
| 82 | + ctx.actions.run_shell( |
| 83 | + outputs = outputs, |
| 84 | + inputs = all_files + [vitis_tcl, ctx.file.xilinx_env], |
| 85 | + progress_message = progress_message, |
| 86 | + command = vitis_command, |
| 87 | + ) |
| 88 | + |
| 89 | + return [ |
| 90 | + DefaultInfo(files = depset(outputs)), |
| 91 | + ] |
| 92 | + |
| 93 | +vitis_generate = rule( |
| 94 | + implementation = _vitis_generate_impl, |
| 95 | + attrs = { |
| 96 | + "top_func": attr.string(doc = "The name of the top level function.", mandatory = True), |
| 97 | + "clock_period": attr.string(doc = "The clock period for the module.", mandatory = True), |
| 98 | + "part_number": attr.string(doc = "The part number to use. Default is ZCU111", default = "xczu28dr-ffvg1517-2-e"), |
| 99 | + "deps": attr.label_list(doc = "The file to generate from", aspects = [vitis_hls_files_aspect], mandatory = True), |
| 100 | + "out": attr.output(doc = "The generated verilog files", mandatory = True), |
| 101 | + "use_vivado_hls": attr.bool(doc = "Use vivado HLS instead of vitis hls.", default = False), |
| 102 | + "_vitis_generate_template": attr.label( |
| 103 | + doc = "The tcl template to run with vitis.", |
| 104 | + default = "@rules_hdl//vitis:vitis_generate.tcl.template", |
| 105 | + allow_single_file = [".template"], |
| 106 | + ), |
| 107 | + "xilinx_env": attr.label( |
| 108 | + doc = "Environment variables for xilinx tools.", |
| 109 | + allow_single_file = [".sh"], |
| 110 | + mandatory = True, |
| 111 | + ), |
| 112 | + }, |
| 113 | +) |
0 commit comments