blob: 242bad340be8877a71662362ecba8b00e4e41dc5 [file] [log] [blame] [edit]
# 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",
),
},
)