From 484e63fbdb0db5fa0d2f63f866e54a2719cec0c4 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C3=98yvind=20Harboe?= Date: Fri, 1 May 2026 13:05:12 +0200 Subject: [PATCH] extension: add `yosys_plugins` attribute to orfs.default() MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Lets consumers expose out-of-tree yosys plugins (e.g. yosys-slang) without having to materialize a custom yosys_share tree. bazel-orfs now derives YOSYS_PLUGIN_PATH from the dirnames of the plugin files passed via `yosys_plugins`, and adds them to the input set of yosys actions. The old single-tree-artifact yosys_share path is preserved as a fallback when no plugins are specified, so existing consumers (including downstream/test) keep working. Tested via The-OpenROAD-Project/OpenROAD#10237 (ditch-docker): - bazelisk build //:openroad clean - bazelisk test //test/orfs/... -- all 19 tests pass - merge_yosys_share custom rule removed in OpenROAD; orfs.default() uses yosys_plugins = ["@yosys-slang//src/yosys_plugin:slang.so"] Signed-off-by: Øyvind Harboe --- config.bzl | 6 ++++++ extension.bzl | 7 +++++++ private/attrs.bzl | 7 +++++++ private/environment.bzl | 20 ++++++++++++++------ 4 files changed, 34 insertions(+), 6 deletions(-) diff --git a/config.bzl b/config.bzl index 9b912a3b..b47a3894 100644 --- a/config.bzl +++ b/config.bzl @@ -6,6 +6,9 @@ def _global_config_impl(repository_ctx): num_cpus = int(result.stdout.strip()) else: num_cpus = 4 + yosys_plugins_repr = "[" + ", ".join( + ['"{}"'.format(p) for p in repository_ctx.attr.yosys_plugins], + ) + "]" repository_ctx.file( "global_config.bzl", """ @@ -19,6 +22,7 @@ CONFIG_PDK = "{pdk}" CONFIG_YOSYS = "{yosys}" CONFIG_YOSYS_ABC = "{yosys_abc}" CONFIG_YOSYS_SHARE = "{yosys_share}" +CONFIG_YOSYS_PLUGINS = {yosys_plugins} NUM_CPUS = {num_cpus} """.format( klayout = repository_ctx.attr.klayout, @@ -31,6 +35,7 @@ NUM_CPUS = {num_cpus} yosys = repository_ctx.attr.yosys, yosys_abc = repository_ctx.attr.yosys_abc, yosys_share = repository_ctx.attr.yosys_share, + yosys_plugins = yosys_plugins_repr, num_cpus = num_cpus, ), ) @@ -68,6 +73,7 @@ global_config = repository_rule( cfg = "exec", ), "yosys_share": attr.label(mandatory = True), + "yosys_plugins": attr.label_list(), }, doc = "A repository that provides global configuration values as strings.", ) diff --git a/extension.bzl b/extension.bzl index d73112b5..baa56a46 100644 --- a/extension.bzl +++ b/extension.bzl @@ -66,6 +66,12 @@ _default_tag = tag_class( mandatory = False, default = Label("@yosys//:yosys_share"), ), + "yosys_plugins": attr.label_list( + mandatory = False, + doc = "Extra .so plugin files to expose via YOSYS_PLUGIN_PATH " + + "during yosys actions. Use to load out-of-tree plugins " + + "(e.g. yosys-slang) without merging them into yosys_share.", + ), }, ) @@ -90,6 +96,7 @@ def _orfs_repositories_impl(module_ctx): yosys = default.yosys, yosys_abc = default.yosys_abc, yosys_share = default.yosys_share, + yosys_plugins = default.yosys_plugins, ) load_json_file( diff --git a/private/attrs.bzl b/private/attrs.bzl index dc8a76a9..23b0124d 100644 --- a/private/attrs.bzl +++ b/private/attrs.bzl @@ -12,6 +12,7 @@ load( "CONFIG_PDK", "CONFIG_YOSYS", "CONFIG_YOSYS_ABC", + "CONFIG_YOSYS_PLUGINS", "CONFIG_YOSYS_SHARE", ) load( @@ -163,6 +164,12 @@ def yosys_only_attrs(): cfg = "exec", default = CONFIG_YOSYS_SHARE, ), + "_yosys_plugins": attr.label_list( + doc = "Extra .so plugin files exposed via YOSYS_PLUGIN_PATH.", + allow_files = True, + cfg = "exec", + default = CONFIG_YOSYS_PLUGINS, + ), } def renamed_inputs_attr(): diff --git a/private/environment.bzl b/private/environment.bzl index 7f0a96ee..265de78d 100644 --- a/private/environment.bzl +++ b/private/environment.bzl @@ -55,11 +55,19 @@ def yosys_environment(ctx): "YOSYS_EXE": ctx.executable.yosys.path, } | orfs_environment(ctx) - # When yosys_share is a single tree artifact (e.g. merged share with - # plugins), tell yosys where to find plugins via YOSYS_PLUGIN_PATH. - # BCR yosys discovers plugins via /proc/self/exe and won't find plugins - # that live outside its own share/ tree without this hint. - if len(ctx.files._yosys_share) == 1: + # Tell yosys where to find out-of-tree plugins (e.g. yosys-slang) + # via YOSYS_PLUGIN_PATH. BCR yosys discovers plugins via + # /proc/self/exe and won't find plugins that live outside its own + # share/ tree without this hint. + plugin_dirs = [] + for f in ctx.files._yosys_plugins: + if f.dirname not in plugin_dirs: + plugin_dirs.append(f.dirname) + if plugin_dirs: + env["YOSYS_PLUGIN_PATH"] = ":".join(plugin_dirs) + elif len(ctx.files._yosys_share) == 1: + # Backwards-compat: a single tree-artifact yosys_share with a + # plugins/ subdir still works. env["YOSYS_PLUGIN_PATH"] = ctx.files._yosys_share[0].path + "/plugins" return env @@ -133,7 +141,7 @@ def test_inputs(ctx): def yosys_inputs(ctx): return depset( - ctx.files._yosys_share, + ctx.files._yosys_share + ctx.files._yosys_plugins, transitive = [ _runfiles( [