feat(build): Add FPGA toolchain support and enhance binary rules
Change-Id: Iede67e519368f5f58ac368cf1d40acc909cd37b0
diff --git a/.bazelrc b/.bazelrc
index 46c1a8c..a78752b 100644
--- a/.bazelrc
+++ b/.bazelrc
@@ -31,16 +31,19 @@
build --action_env=VC_STATIC_HOME
build --action_env=VERDI_HOME
build --action_env=LM_LICENSE_FILE
+build --action_env=XILINXD_LICENSE_FILE
test --build_tag_filters="-vcs,-renode,-verilator,-synthesis"
test --test_tag_filters="-vcs,-renode,-verilator,-synthesis"
test --action_env=VCS_HOME
test --action_env=VC_STATIC_HOME
test --action_env=VERDI_HOME
test --action_env=LM_LICENSE_FILE
+test --action_env=XILINXD_LICENSE_FILE
run --action_env=VCS_HOME
run --action_env=VC_STATIC_HOME
run --action_env=VERDI_HOME
run --action_env=LM_LICENSE_FILE
+run --action_env=XILINXD_LICENSE_FILE
# Add config to enable VCS targets.
build:vcs --build_tag_filters="vcs"
diff --git a/WORKSPACE b/WORKSPACE
index ec83784..187ab52 100644
--- a/WORKSPACE
+++ b/WORKSPACE
@@ -14,7 +14,7 @@
workspace(name = "kelvin_hw")
-load("//rules:repos.bzl", "kelvin_repos", "renode_repos", "cvfpu_repos", "rvvi_repos")
+load("//rules:repos.bzl", "kelvin_repos", "renode_repos", "cvfpu_repos", "rvvi_repos", "fpga_repos")
kelvin_repos()
@@ -88,10 +88,47 @@
python_version = "3.9",
)
+fpga_repos()
+
+load("@lowrisc_opentitan_gh//rules:nonhermetic.bzl", "nonhermetic_repo")
+
+nonhermetic_repo(name = "nonhermetic")
+
+load("@bazel_tools//tools/build_defs/repo:http.bzl", "http_archive")
+
+load("@rules_python//python:pip.bzl", "pip_parse")
+
+pip_parse(
+ name = "ot_python_deps",
+ requirements_lock = "@lowrisc_opentitan_gh//:python-requirements.txt",
+ python_interpreter_target = "@python39_x86_64-unknown-linux-gnu//:python",
+)
+
load("//third_party/python:requirements.bzl", "install_deps")
install_deps()
-load("@bazel_tools//tools/build_defs/repo:http.bzl", "http_archive")
+# OpenTitan's requirements need this, but for some reason do not provide it.
+http_archive(
+ name = "ot_python_deps_importlib_metadata",
+ urls = [
+ "https://files.pythonhosted.org/packages/20/b0/36bd937216ec521246249be3bf9855081de4c5e06a0c9b4219dbeda50373/importlib_metadata-8.7.0-py3-none-any.whl",
+ ],
+ sha256 = "e5dd1551894c77868a30651cef00984d50e1002d06942a7101d34870c5f02afd",
+ type = "zip",
+ build_file_content = """
+package(default_visibility = ["//visibility:public"])
+py_library(
+ name = "pkg",
+ srcs = glob(["**/*.py"]),
+ data = [] + glob(["**/*"], exclude=["**/* *", "**/*.dist-info/RECORD", "**/*.py", "**/*.pyc"]),
+ imports = ["."],
+ tags = ["pypi_name=importlib_metadata","pypi_version=8.7.0"],
+)
+""",
+)
+
+load("@ot_python_deps//:requirements.bzl", ot_install_deps = "install_deps")
+ot_install_deps()
http_archive(
name = "toolchain_kelvin_v2",
diff --git a/fpga/0001-Export-hw-ip_templates.patch b/fpga/0001-Export-hw-ip_templates.patch
new file mode 100644
index 0000000..4620e1b
--- /dev/null
+++ b/fpga/0001-Export-hw-ip_templates.patch
@@ -0,0 +1,44 @@
+From 626a4c6e202972b7930797cb7a43f8ee6ac6b991 Mon Sep 17 00:00:00 2001
+From: Alex Van Damme <atv@google.com>
+Date: Fri, 18 Jul 2025 14:48:57 -0700
+Subject: [PATCH] Export hw/ip_templates
+
+---
+ hw/BUILD | 3 +--
+ hw/ip_templates/BUILD | 2 ++
+ 2 files changed, 3 insertions(+), 2 deletions(-)
+
+diff --git a/hw/BUILD b/hw/BUILD
+index 2fb71c7d81..d7e28a91a8 100644
+--- a/hw/BUILD
++++ b/hw/BUILD
+@@ -15,7 +15,7 @@ load("@bazel_skylib//rules:common_settings.bzl", "string_list_flag")
+
+ package(default_visibility = ["//visibility:public"])
+
+-exports_files(["tool_requirements.py"])
++exports_files(["tool_requirements.py"] + glob(["vendor/lowrisc_ibex/**"]))
+
+ filegroup(
+ name = "doc_files",
+@@ -177,7 +177,6 @@ filegroup(
+ # dv_macros are needed by Ibex, so include this back in.
+ "//hw/dv/sv:dv_macros",
+ "//hw/ip:rtl_files",
+- "//hw/top_earlgrey:rtl_files",
+ ],
+ visibility = ["//visibility:public"],
+ )
+diff --git a/hw/ip_templates/BUILD b/hw/ip_templates/BUILD
+index 3e8bb41965..a9431cda2e 100644
+--- a/hw/ip_templates/BUILD
++++ b/hw/ip_templates/BUILD
+@@ -1,3 +1,5 @@
+ # Copyright lowRISC contributors (OpenTitan project).
+ # Licensed under the Apache License, Version 2.0, see LICENSE for details.
+ # SPDX-License-Identifier: Apache-2.0
++
++exports_files(glob(["**"]))
+--
+2.50.0.727.gbf7dc18ff4-goog
+
diff --git a/fpga/BUILD b/fpga/BUILD
new file mode 100644
index 0000000..36a1e8d
--- /dev/null
+++ b/fpga/BUILD
@@ -0,0 +1,14 @@
+# Copyright 2025 Google LLC
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+
diff --git a/rules/kelvin_v2.bzl b/rules/kelvin_v2.bzl
index 3a4dc6d..22423da 100644
--- a/rules/kelvin_v2.bzl
+++ b/rules/kelvin_v2.bzl
@@ -87,14 +87,23 @@
if CcInfo in dep:
compilation_contexts.append(dep[CcInfo].compilation_context)
linking_contexts.append(dep[CcInfo].linking_context)
+
+ sources = []
+ headers = []
+ for src in ctx.files.srcs:
+ if src.extension in ["h", "hh", "hpp"]:
+ headers.append(src)
+ else:
+ sources.append(src)
+
(_compilation_context, compilation_outputs) = cc_common.compile(
actions = ctx.actions,
cc_toolchain = cc_toolchain,
feature_configuration = feature_configuration,
name = ctx.label.name,
- srcs = ctx.files.srcs,
+ srcs = sources,
compilation_contexts = compilation_contexts,
- private_hdrs = ctx.files.hdrs,
+ private_hdrs = headers + ctx.files.hdrs,
user_compile_flags = ctx.attr.copts,
defines = ctx.attr.defines,
)
@@ -112,13 +121,58 @@
output_type = "executable",
)
+ out_bin = ctx.actions.declare_file("{}.bin".format(ctx.label.name))
+ objcopy_tool = cc_toolchain.objcopy_executable
+
+ ctx.actions.run(
+ outputs = [out_bin],
+ inputs = [linking_outputs.executable] + cc_toolchain.all_files.to_list(),
+ executable = objcopy_tool,
+ arguments = [
+ "-O",
+ "binary",
+ linking_outputs.executable.path,
+ out_bin.path,
+ ],
+ mnemonic = "ObjCopy",
+ )
+
+ out_vmem = ctx.actions.declare_file("{}.vmem".format(ctx.label.name))
+ word_size = ctx.attr.word_size
+ srec_cat_vmem_args = [
+ out_bin.path,
+ "-binary",
+ "-byte-swap",
+ str(word_size // 8),
+ "-fill",
+ "0xff",
+ "-within",
+ out_bin.path,
+ "-binary",
+ "-range-pad",
+ str(word_size // 8),
+ "-o",
+ out_vmem.path,
+ "-vmem",
+ str(word_size),
+ ]
+ ctx.actions.run(
+ outputs = [out_vmem],
+ inputs = [out_bin],
+ executable = "srec_cat",
+ arguments = srec_cat_vmem_args,
+ mnemonic = "SrecCat",
+ )
+
return [
DefaultInfo(
- files = depset([linking_outputs.executable]),
+ files = depset([linking_outputs.executable, out_bin, out_vmem]),
),
OutputGroupInfo(
- all_files = depset([linking_outputs.executable]),
+ all_files = depset([linking_outputs.executable, out_bin, out_vmem]),
elf_file = depset([linking_outputs.executable]),
+ bin_file = depset([out_bin]),
+ vmem_file = depset([out_vmem]),
),
]
@@ -134,6 +188,7 @@
"linker_script": attr.label(allow_single_file = True),
"linker_script_includes": attr.label_list(default = [], allow_files = True),
"semihosting": attr.bool(),
+ "word_size": attr.int(default = 32),
"_cc_toolchain": attr.label(default = Label("@bazel_tools//tools/cpp:current_cc_toolchain")),
},
fragments = ["cpp"],
@@ -145,6 +200,8 @@
srcs,
tags = [],
semihosting = False,
+ linker_script = "@kelvin_hw//toolchain:kelvin_tcm.ld",
+ word_size = 32,
**kwargs):
"""A helper macro for generating binary artifacts for the Kelvin V2 core.
@@ -156,6 +213,7 @@
srcs: The c source files.
tags: build tags.
semihosting: Enable htif-style semihosting
+ linker_script: Linker script to construct the final binary.
**kwargs: Additional arguments forward to cc_binary.
Emits rules:
filegroup named: <name>.bin
@@ -171,10 +229,11 @@
_kelvin_v2_binary(
name = name,
srcs = srcs,
- linker_script = "@kelvin_hw//toolchain:kelvin_tcm.ld",
+ linker_script = linker_script,
semihosting = semihosting,
tags = tags,
deps = deps,
+ word_size = word_size,
**kwargs
)
@@ -183,4 +242,18 @@
srcs = [name],
output_group = "elf_file",
tags = tags,
+ )
+
+ native.filegroup(
+ name = "{}.vmem".format(name),
+ srcs = [name],
+ output_group = "vmem_file",
+ tags = tags,
+ )
+
+ native.filegroup(
+ name = "{}.bin".format(name),
+ srcs = [name],
+ output_group = "bin_file",
+ tags = tags,
)
\ No newline at end of file
diff --git a/rules/repos.bzl b/rules/repos.bzl
index 64cb1c0..4b18ee6 100644
--- a/rules/repos.bzl
+++ b/rules/repos.bzl
@@ -160,3 +160,15 @@
],
patch_args = ["-p1"],
)
+
+def fpga_repos():
+ http_archive(
+ name = "lowrisc_opentitan_gh",
+ urls = ["https://github.com/lowRISC/opentitan/archive/1b1945fd76799666156f817e163222725c518c59.zip"],
+ sha256 = "b881378cdffee2284a88c2032c9fb13e68c889f1cac38cf715b0cff7b40fcf7e",
+ strip_prefix = "opentitan-1b1945fd76799666156f817e163222725c518c59",
+ patches = [
+ "@kelvin_hw//fpga:0001-Export-hw-ip_templates.patch",
+ ],
+ patch_args = ["-p1"],
+ )
\ No newline at end of file
diff --git a/rules/utils.bzl b/rules/utils.bzl
index a877032..be8ec88 100644
--- a/rules/utils.bzl
+++ b/rules/utils.bzl
@@ -44,4 +44,34 @@
rule(
name = rule_name,
**rule_kwargs
- )
\ No newline at end of file
+ )
+
+def cc_embed_data(
+ name,
+ srcs,
+ var_name = "data",
+ testonly = False,
+ **kwargs):
+ """A rule to merge binary files into a C include file.
+ Args:
+ name: The name of the target.
+ srcs: The input binary source files.
+ var_name: The variable name of the array in output C include file.
+ testonly: The target is built for test only.
+ **kwargs: Extra arguments forwards to genrule.
+ """
+ xxd_cmd = """
+ xxd -i $< > $@;
+ sed -i -e 's#\\w*_len#{}_len#g' $@;
+ sed -i -e "s#\\w*\\[\\]#{}\\[\\]#g" $@;
+ sed -i -e 's/unsigned/const unsigned/g' $@
+ """.format(var_name, var_name)
+ outs = ["{}.{}".format(name, "h")]
+ native.genrule(
+ name = name,
+ srcs = srcs,
+ outs = outs,
+ cmd = xxd_cmd,
+ testonly = testonly,
+ **kwargs
+ )
diff --git a/third_party/python/BUILD b/third_party/python/BUILD
index 0a2669d..a4c83a0 100644
--- a/third_party/python/BUILD
+++ b/third_party/python/BUILD
@@ -11,3 +11,5 @@
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
+
+package(default_visibility = ["//visibility:public"])
diff --git a/third_party/python/requirements.bzl b/third_party/python/requirements.bzl
index 2fedda3..b5fed94 100644
--- a/third_party/python/requirements.bzl
+++ b/third_party/python/requirements.bzl
@@ -364,3 +364,40 @@
],
),
)
+
+ # FPGA
+ http_archive(
+ name = "kelvin_pip_deps_mako",
+ urls = [
+ "https://files.pythonhosted.org/packages/87/fb/99f81ac72ae23375f22b7afdb7642aba97c00a713c217124420147681a2f/mako-1.3.10-py3-none-any.whl",
+ ],
+ sha256 = "baef24a52fc4fc514a0887ac600f9f1cff3d82c61d4d700a1fa84d597b88db59",
+ type = "zip",
+ build_file_content = _build_file_content(pypi_name = "mako", pypi_version = "1.3.10"),
+ )
+
+ http_archive(
+ name = "kelvin_pip_deps_hjson",
+ urls = [
+ "https://files.pythonhosted.org/packages/1f/7f/13cd798d180af4bf4c0ceddeefba2b864a63c71645abc0308b768d67bb81/hjson-3.1.0-py3-none-any.whl",
+ ],
+ sha256 = "65713cdcf13214fb554eb8b4ef803419733f4f5e551047c9b711098ab7186b89",
+ type = "zip",
+ build_file_content = _build_file_content(pypi_name = "hjson", pypi_version = "3.1.0"),
+ )
+
+ http_archive(
+ name = "kelvin_pip_deps_fusesoc",
+ urls = [
+ "https://files.pythonhosted.org/packages/cb/a8/10f62458dda2ca07c49477448e643b10f30825b7741fdb6ec3e6188b6999/fusesoc-2.4.3-py3-none-any.whl",
+ ],
+ sha256 = "9ab4a82a5b7d4decbeb8f76049673a1b0806732ab8f807fee285bbc0452b3dc3",
+ type = "zip",
+ build_file_content = _build_file_content(
+ pypi_name = "fusesoc",
+ pypi_version = "2.4.3",
+ deps = [
+ "@kelvin_pip_deps_hjson//:pkg",
+ ],
+ ),
+ )
diff --git a/toolchain/cc_toolchain_config.bzl b/toolchain/cc_toolchain_config.bzl
index 44a5d1b..b86d290 100644
--- a/toolchain/cc_toolchain_config.bzl
+++ b/toolchain/cc_toolchain_config.bzl
@@ -76,6 +76,10 @@
path = "/bin/false",
),
tool_path(
+ name = "objcopy",
+ path = "wrappers/objcopy",
+ ),
+ tool_path(
name = "strip",
path = "/bin/false",
),
diff --git a/toolchain/wrappers/objcpy b/toolchain/wrappers/objcpy
deleted file mode 120000
index da2bdd9..0000000
--- a/toolchain/wrappers/objcpy
+++ /dev/null
@@ -1 +0,0 @@
-driver.sh
\ No newline at end of file