| # Copyright lowRISC contributors. |
| # Licensed under the Apache License, Version 2.0, see LICENSE for details. |
| # SPDX-License-Identifier: Apache-2.0 |
| |
| load("@nonhermetic//:env.bzl", "ENV") |
| load("@ot_python_deps//:requirements.bzl", "entry_point") |
| |
| """Rules for running FuseSoC. |
| |
| FuseSoC is a package manager and set of build tools for HDL code. |
| |
| Because we want the output of some FuseSoC built resources to be |
| available to bazel (such as the verilated chip model for running |
| tests), the `fusesoc_build` rule allows bazel to delegate certain |
| targets to FuseSoC. |
| |
| This rule is not sandboxed, as our current configuration depends |
| on FuseSoC and its dependencies (verible, verilator, etc) already |
| having been installed. In the future, we will try to rework our |
| dependencies so the FuseSoC rules can be sandboxed. |
| """ |
| |
| load("@bazel_skylib//rules:common_settings.bzl", "BuildSettingInfo") |
| |
| def _corefiles2rootarg(core): |
| return core.dirname |
| |
| def _fusesoc_build_impl(ctx): |
| dirname = "build.{}".format(ctx.label.name) |
| out_dir = ctx.actions.declare_directory(dirname) |
| flags = [ctx.expand_location(f, ctx.attr.srcs) for f in ctx.attr.flags] |
| outputs = [out_dir] |
| groups = {} |
| args = ctx.actions.args() |
| |
| for group, files in ctx.attr.output_groups.items(): |
| deps = [ctx.actions.declare_file("{}/{}".format(dirname, f)) for f in files] |
| outputs.extend(deps) |
| groups[group] = depset(deps) |
| |
| if ctx.attr.verilator_options: |
| verilator_options = ctx.attr.verilator_options[BuildSettingInfo].value |
| flags.append("--verilator_options={}".format(" ".join(verilator_options))) |
| |
| if ctx.attr.make_options: |
| make_options = ctx.attr.make_options[BuildSettingInfo].value |
| flags.append("--make_options={}".format(" ".join(make_options))) |
| |
| args.add_all( |
| ctx.files.cores, |
| uniquify = True, |
| map_each = _corefiles2rootarg, |
| format_each = "--cores-root=%s", |
| ) |
| |
| args.add_all([ |
| "run", |
| "--flag=fileset_top", |
| ]) |
| args.add(ctx.attr.target, format = "--target=%s") |
| args.add_all([ |
| "--setup", |
| "--build", |
| ]) |
| args.add(out_dir.path, format = "--build-root=%s") |
| |
| args.add_all(ctx.attr.systems) |
| args.add_all(flags) |
| |
| _inputs = ctx.files.srcs + ctx.files.cores |
| |
| # For some reason, the sanboxed fusesoc would call vivado twice. Add an |
| # option to use the system installed fusesoc. |
| if ctx.attr.use_system_fusesoc: |
| _exec = "fusesoc" |
| else: |
| _exec = ctx.executable._fusesoc |
| _inputs += ctx.files._fusesoc |
| |
| # Note: the `fileset_top` flag used above is specific to the OpenTitan |
| # project to select the correct RTL fileset. |
| ctx.actions.run( |
| mnemonic = "FuseSoC", |
| outputs = outputs, |
| inputs = _inputs, |
| arguments = [args], |
| executable = _exec, |
| use_default_shell_env = False, |
| execution_requirements = { |
| "no-sandbox": "", |
| }, |
| env = ENV, |
| ) |
| return [ |
| DefaultInfo( |
| files = depset(outputs), |
| data_runfiles = ctx.runfiles(files = outputs + ctx.files.data), |
| ), |
| OutputGroupInfo(**groups), |
| ] |
| |
| fusesoc_build = rule( |
| implementation = _fusesoc_build_impl, |
| attrs = { |
| "cores": attr.label_list(allow_files = True, doc = "FuseSoC core specification files"), |
| "srcs": attr.label_list(allow_files = True, doc = "Source files"), |
| "data": attr.label_list(allow_files = True, doc = "Files needed at runtime"), |
| "target": attr.string(mandatory = True, doc = "Target name (e.g. 'sim')"), |
| "systems": attr.string_list(mandatory = True, doc = "Systems to build"), |
| "flags": attr.string_list(doc = "Flags controlling the FuseSOC system build"), |
| "output_groups": attr.string_list_dict( |
| allow_empty = True, |
| doc = "Mapping of group name to lists of files in that named group", |
| ), |
| "verilator_options": attr.label(), |
| "make_options": attr.label(), |
| "use_system_fusesoc": attr.bool( |
| default = False, |
| doc = "Use non-sanboxed fusesoc (for FPGA vivado build)", |
| ), |
| "_fusesoc": attr.label( |
| default = entry_point("fusesoc"), |
| executable = True, |
| cfg = "exec", |
| ), |
| }, |
| ) |