Chris Frantz | 9b34e4a | 2021-11-24 17:03:12 -0800 | [diff] [blame] | 1 | # Copyright lowRISC contributors. |
| 2 | # Licensed under the Apache License, Version 2.0, see LICENSE for details. |
| 3 | # SPDX-License-Identifier: Apache-2.0 |
| 4 | |
Miguel Young de la Sota | 3b5a9f5 | 2022-03-24 16:11:42 -0400 | [diff] [blame] | 5 | load("//rules:rv.bzl", "rv_rule") |
Miguel Young de la Sota | 4b01c7a | 2022-04-21 17:25:52 -0400 | [diff] [blame] | 6 | load("@rules_cc//cc:find_cc_toolchain.bzl", "find_cc_toolchain") |
Chris Frantz | 9b34e4a | 2021-11-24 17:03:12 -0800 | [diff] [blame] | 7 | |
Jade Philipoom | 39c9b32 | 2022-03-08 12:27:10 +0000 | [diff] [blame] | 8 | def _get_assembler(cc_toolchain): |
| 9 | """Find the path to riscv-unknown-elf-as.""" |
| 10 | |
Miguel Young de la Sota | 8fce79d | 2022-03-23 15:37:39 -0400 | [diff] [blame] | 11 | # Note: the toolchain config doesn"t appear to have a good way to get |
| 12 | # access to the assembler. We should be able to access it via the |
Timothy Trippel | efe736b | 2022-04-20 12:50:40 -0700 | [diff] [blame] | 13 | # the compiler, but I had trouble with //hw/ip/otbn/util/otbn_as.py invoking |
Miguel Young de la Sota | 8fce79d | 2022-03-23 15:37:39 -0400 | [diff] [blame] | 14 | # the compiler as assembler. |
Jade Philipoom | 39c9b32 | 2022-03-08 12:27:10 +0000 | [diff] [blame] | 15 | return [f for f in cc_toolchain.all_files.to_list() if f.basename.endswith("as")][0] |
| 16 | |
| 17 | def _otbn_assemble_sources(ctx): |
| 18 | """Helper function that, for each source file in the provided context, adds |
Timothy Trippel | efe736b | 2022-04-20 12:50:40 -0700 | [diff] [blame] | 19 | an action to the context that invokes the otbn assember (otbn_as.py), |
Jade Philipoom | 39c9b32 | 2022-03-08 12:27:10 +0000 | [diff] [blame] | 20 | producing a corresponding object file. Returns a list of all object files |
| 21 | that will be generated by these actions. |
| 22 | """ |
Miguel Young de la Sota | 4b01c7a | 2022-04-21 17:25:52 -0400 | [diff] [blame] | 23 | cc_toolchain = find_cc_toolchain(ctx).cc |
Jade Philipoom | 39c9b32 | 2022-03-08 12:27:10 +0000 | [diff] [blame] | 24 | assembler = _get_assembler(cc_toolchain) |
| 25 | |
| 26 | objs = [] |
| 27 | for src in ctx.files.srcs: |
| 28 | obj = ctx.actions.declare_file(src.basename.replace("." + src.extension, ".o")) |
| 29 | objs.append(obj) |
| 30 | ctx.actions.run( |
| 31 | outputs = [obj], |
| 32 | inputs = ([src] + |
| 33 | cc_toolchain.all_files.to_list() + |
Timothy Trippel | fc19734 | 2022-04-20 14:38:11 -0700 | [diff] [blame] | 34 | [ctx.executable._otbn_as]), |
Jade Philipoom | 39c9b32 | 2022-03-08 12:27:10 +0000 | [diff] [blame] | 35 | env = { |
| 36 | "RV32_TOOL_AS": assembler.path, |
| 37 | }, |
| 38 | arguments = ["-o", obj.path, src.path], |
Timothy Trippel | fc19734 | 2022-04-20 14:38:11 -0700 | [diff] [blame] | 39 | executable = ctx.executable._otbn_as, |
Jade Philipoom | 39c9b32 | 2022-03-08 12:27:10 +0000 | [diff] [blame] | 40 | ) |
| 41 | |
| 42 | return objs |
| 43 | |
| 44 | def _otbn_library(ctx): |
| 45 | """Produces a collection of object files, one per source file, that can be |
| 46 | used as a dependency for otbn binaries.""" |
| 47 | objs = _otbn_assemble_sources(ctx) |
| 48 | |
| 49 | return [ |
Timothy Trippel | fc19734 | 2022-04-20 14:38:11 -0700 | [diff] [blame] | 50 | DefaultInfo( |
| 51 | files = depset(objs), |
| 52 | data_runfiles = ctx.runfiles(files = objs), |
| 53 | ), |
Jade Philipoom | 39c9b32 | 2022-03-08 12:27:10 +0000 | [diff] [blame] | 54 | ] |
| 55 | |
Chris Frantz | 9b34e4a | 2021-11-24 17:03:12 -0800 | [diff] [blame] | 56 | def _otbn_binary(ctx): |
| 57 | """The build process for otbn resources currently invokes |
Timothy Trippel | fc19734 | 2022-04-20 14:38:11 -0700 | [diff] [blame] | 58 | `//hw/ip/otbn/util/otbn_{as,ld,...}.py` to build the otbn resource. |
Chris Frantz | 9b34e4a | 2021-11-24 17:03:12 -0800 | [diff] [blame] | 59 | These programs are python scripts which translate otbn special |
| 60 | instructions into the proper opcode sequences and _then_ invoke the normal |
| 61 | `rv32-{as,ld,...}` programs to produce the resource. These "native" |
| 62 | otbn resources are the `otbn_objs` and `elf` output groups. |
| 63 | |
| 64 | In order to make the otbn resource useful to the the main CPU, the |
| 65 | otbn resource needs to be included as a blob of data that the main |
| 66 | CPU can dump into the otbn `imem` area and ask otbn to execute it. |
| 67 | `util/otbn-build.py` does this with some objcopy-fu, emitting |
| 68 | `foo.rv32embed.o`. Bazel's `cc_*` rules really want dependency objects |
| 69 | expressed as archives rather than raw object files, so I've modified |
| 70 | `otbn-build` to also emit an archive file. |
| 71 | |
| 72 | _Morally_, the otbn resource is a data dependency. However the |
| 73 | practical meaning of a `data` dependency in bazel is a file made |
| 74 | available at runtime, which is not how we're using the otbn resource. |
| 75 | The closest analog is something like `cc_embed_data`, which is like |
| 76 | a data dependency that needs to be linked into the main program. |
Timothy Trippel | fc19734 | 2022-04-20 14:38:11 -0700 | [diff] [blame] | 77 | We achieve by having `otbn_build.py` emit a conventional RV32I library |
Chris Frantz | 9b34e4a | 2021-11-24 17:03:12 -0800 | [diff] [blame] | 78 | that other rules can depend on in their `deps`. |
| 79 | """ |
Miguel Young de la Sota | 4b01c7a | 2022-04-21 17:25:52 -0400 | [diff] [blame] | 80 | cc_toolchain = find_cc_toolchain(ctx).cc |
Jade Philipoom | 39c9b32 | 2022-03-08 12:27:10 +0000 | [diff] [blame] | 81 | assembler = _get_assembler(cc_toolchain) |
| 82 | |
| 83 | # Run the otbn assembler on source files to produce object (.o) files. |
| 84 | objs = _otbn_assemble_sources(ctx) |
| 85 | |
| 86 | # Declare output files. |
Chris Frantz | 9b34e4a | 2021-11-24 17:03:12 -0800 | [diff] [blame] | 87 | elf = ctx.actions.declare_file(ctx.attr.name + ".elf") |
| 88 | rv32embed = ctx.actions.declare_file(ctx.attr.name + ".rv32embed.o") |
| 89 | archive = ctx.actions.declare_file(ctx.attr.name + ".rv32embed.a") |
Chris Frantz | 9b34e4a | 2021-11-24 17:03:12 -0800 | [diff] [blame] | 90 | |
Jade Philipoom | 39c9b32 | 2022-03-08 12:27:10 +0000 | [diff] [blame] | 91 | deps = [f for dep in ctx.attr.deps for f in dep.files.to_list()] |
Chris Frantz | 9b34e4a | 2021-11-24 17:03:12 -0800 | [diff] [blame] | 92 | |
Jade Philipoom | 39c9b32 | 2022-03-08 12:27:10 +0000 | [diff] [blame] | 93 | # Run the otbn_build.py script to link object files from the sources and |
| 94 | # dependencies. |
Chris Frantz | 9b34e4a | 2021-11-24 17:03:12 -0800 | [diff] [blame] | 95 | ctx.actions.run( |
Jade Philipoom | 39c9b32 | 2022-03-08 12:27:10 +0000 | [diff] [blame] | 96 | outputs = [elf, rv32embed, archive], |
| 97 | inputs = (objs + |
| 98 | deps + |
Chris Frantz | 9b34e4a | 2021-11-24 17:03:12 -0800 | [diff] [blame] | 99 | cc_toolchain.all_files.to_list() + |
Chris Frantz | 9b34e4a | 2021-11-24 17:03:12 -0800 | [diff] [blame] | 100 | ctx.files._otbn_data + |
Timothy Trippel | 024e393 | 2022-04-20 15:40:55 -0700 | [diff] [blame] | 101 | [ctx.executable._wrapper]), |
Chris Frantz | 9b34e4a | 2021-11-24 17:03:12 -0800 | [diff] [blame] | 102 | env = { |
Chris Frantz | 9b34e4a | 2021-11-24 17:03:12 -0800 | [diff] [blame] | 103 | "RV32_TOOL_AS": assembler.path, |
| 104 | "RV32_TOOL_AR": cc_toolchain.ar_executable, |
| 105 | "RV32_TOOL_LD": cc_toolchain.ld_executable, |
| 106 | "RV32_TOOL_OBJCOPY": cc_toolchain.objcopy_executable, |
| 107 | }, |
| 108 | arguments = [ |
| 109 | "--app-name={}".format(ctx.attr.name), |
| 110 | "--archive", |
Jade Philipoom | 39c9b32 | 2022-03-08 12:27:10 +0000 | [diff] [blame] | 111 | "--no-assembler", |
Chris Frantz | 9b34e4a | 2021-11-24 17:03:12 -0800 | [diff] [blame] | 112 | "--out-dir={}".format(elf.dirname), |
Jade Philipoom | 39c9b32 | 2022-03-08 12:27:10 +0000 | [diff] [blame] | 113 | ] + [obj.path for obj in (objs + deps)], |
Timothy Trippel | 024e393 | 2022-04-20 15:40:55 -0700 | [diff] [blame] | 114 | executable = ctx.executable._wrapper, |
Chris Frantz | 9b34e4a | 2021-11-24 17:03:12 -0800 | [diff] [blame] | 115 | ) |
| 116 | |
| 117 | feature_configuration = cc_common.configure_features( |
| 118 | ctx = ctx, |
| 119 | cc_toolchain = cc_toolchain, |
| 120 | requested_features = ctx.features, |
| 121 | unsupported_features = ctx.disabled_features, |
| 122 | ) |
| 123 | |
Jade Philipoom | 39c9b32 | 2022-03-08 12:27:10 +0000 | [diff] [blame] | 124 | outputs = objs + [elf, rv32embed, archive] |
Chris Frantz | 9b34e4a | 2021-11-24 17:03:12 -0800 | [diff] [blame] | 125 | return [ |
| 126 | DefaultInfo(files = depset(outputs), data_runfiles = ctx.runfiles(files = outputs)), |
| 127 | OutputGroupInfo( |
Jade Philipoom | 39c9b32 | 2022-03-08 12:27:10 +0000 | [diff] [blame] | 128 | otbn_objs = depset(objs + deps), |
Chris Frantz | 9b34e4a | 2021-11-24 17:03:12 -0800 | [diff] [blame] | 129 | elf = depset([elf]), |
| 130 | rv32embed = depset([rv32embed]), |
| 131 | archive = depset([archive]), |
| 132 | ), |
| 133 | # Emit a CcInfo provider so that this rule can be a dependency in other |
| 134 | # cc_* rules. |
| 135 | CcInfo( |
| 136 | linking_context = cc_common.create_linking_context( |
| 137 | linker_inputs = depset([cc_common.create_linker_input( |
| 138 | owner = ctx.label, |
| 139 | libraries = depset([cc_common.create_library_to_link( |
| 140 | actions = ctx.actions, |
| 141 | feature_configuration = feature_configuration, |
| 142 | cc_toolchain = cc_toolchain, |
| 143 | static_library = archive, |
| 144 | )]), |
| 145 | )]), |
| 146 | ), |
| 147 | ), |
| 148 | ] |
| 149 | |
Jade Philipoom | 6195eef | 2022-04-19 10:32:36 +0100 | [diff] [blame] | 150 | def _otbn_sim_test(ctx): |
| 151 | """This rule is for standalone OTBN unit tests, which are run on the host |
| 152 | via the OTBN simulator. |
| 153 | |
| 154 | It first generates binaries using the same method as otbn_binary, then runs |
| 155 | them on the simulator. Tests are expected to count failures in the w0 |
| 156 | register; the test checks that w0=0 to determine if the test passed. |
| 157 | """ |
| 158 | providers = _otbn_binary(ctx) |
| 159 | |
| 160 | # Extract the output .elf file from the output group. |
| 161 | elf = providers[1].elf.to_list()[0] |
| 162 | |
| 163 | # Create a simple script that runs the OTBN simulator on the .elf file and |
| 164 | # checks if the w0 register is 0. |
| 165 | simulator_cmd = "{} {} --dump-regs -".format(ctx.file._simulator.path, elf.short_path) |
| 166 | expected_string = "0x" + ("0" * 64) |
| 167 | script = ''' |
| 168 | echo "Running simulator: {simulator_cmd}" |
| 169 | result=$({simulator_cmd} | grep -m 1 -P "w0 = [0-9A-Fa-f]+") |
| 170 | echo "Got : $result" |
| 171 | echo "Expected: w0 = {expected_string}" |
| 172 | if [[ "$result" == *"{expected_string}" ]]; then |
| 173 | echo "PASS" |
| 174 | exit 0 |
| 175 | fi |
| 176 | echo "FAIL" |
| 177 | exit 1 |
| 178 | '''.format(simulator_cmd = simulator_cmd, expected_string = expected_string) |
| 179 | script_file = ctx.actions.declare_file("run_{}.sh".format(elf.basename)) |
| 180 | ctx.actions.write( |
| 181 | output = script_file, |
| 182 | content = script, |
| 183 | ) |
| 184 | |
| 185 | # The simulator and .elf file must be added to runfiles in order to be |
| 186 | # visible to the test at runtime. |
| 187 | runfiles = ctx.runfiles(files = (ctx.files.srcs + [elf, ctx.file._simulator])) |
Jade Philipoom | 6b746f7 | 2022-08-01 09:52:15 +0100 | [diff] [blame] | 188 | return [ |
| 189 | DefaultInfo(runfiles = runfiles, executable = script_file), |
| 190 | providers[1], |
| 191 | ] |
| 192 | |
| 193 | def _otbn_consttime_test_impl(ctx): |
| 194 | """This rule checks if a program or subroutine is constant-time. |
| 195 | |
| 196 | There are some limitations to this check; see the Python script's |
| 197 | documentation for details. In particular, the check may not be able to |
| 198 | determine that a program runs in constant-time when in fact it does. |
| 199 | However, if the check passes, the program should always run in constant |
| 200 | time; that is, the check can produce false negatives but never false |
| 201 | positives. |
| 202 | |
| 203 | This rule expects one dependency of an otbn_binary or otbn_sim_test type, |
| 204 | which should provide exactly one `.elf` file. |
| 205 | """ |
| 206 | |
| 207 | # Extract the output .elf file from the output group. |
| 208 | elf = [f for t in ctx.attr.deps for f in t[OutputGroupInfo].elf.to_list()] |
| 209 | if len(elf) != 1: |
| 210 | fail("Expected only one .elf file in dependencies, got: " + str(elf)) |
| 211 | elf = elf[0] |
| 212 | |
| 213 | # Write a very simple script that runs the checker. |
| 214 | script_content = "{} {} --verbose".format(ctx.executable._checker.short_path, elf.short_path) |
| 215 | if ctx.attr.subroutine: |
| 216 | script_content += " --subroutine {}".format(ctx.attr.subroutine) |
| 217 | if ctx.attr.secrets: |
| 218 | script_content += " --secrets {}".format(" ".join(ctx.attr.secrets)) |
Jade Philipoom | 18a7479 | 2022-08-08 17:15:19 +0100 | [diff] [blame] | 219 | if ctx.attr.initial_constants: |
| 220 | script_content += " --constants {}".format(" ".join(ctx.attr.initial_constants)) |
Jade Philipoom | 6b746f7 | 2022-08-01 09:52:15 +0100 | [diff] [blame] | 221 | ctx.actions.write( |
| 222 | output = ctx.outputs.executable, |
| 223 | content = script_content, |
| 224 | ) |
| 225 | |
| 226 | # The .elf file must be added to runfiles in order to be visible to the |
| 227 | # test at runtime. In addition, we need to add all the runfiles from the |
| 228 | # checker script itself (e.g. the Python runtime and dependencies). |
| 229 | runfiles = ctx.runfiles(files = [elf]) |
| 230 | runfiles = runfiles.merge(ctx.attr._checker[DefaultInfo].default_runfiles) |
| 231 | return [DefaultInfo(runfiles = runfiles)] |
Jade Philipoom | 6195eef | 2022-04-19 10:32:36 +0100 | [diff] [blame] | 232 | |
Jade Philipoom | f05ed4d | 2022-07-28 17:27:21 +0100 | [diff] [blame] | 233 | def _otbn_insn_count_range(ctx): |
| 234 | """This rule gets min/max possible instruction counts for an OTBN program. |
| 235 | """ |
| 236 | |
| 237 | # Extract the .elf file to check from the dependency list. |
| 238 | elf = [f for t in ctx.attr.deps for f in t[OutputGroupInfo].elf.to_list()] |
| 239 | if len(elf) != 1: |
| 240 | fail("Expected only one .elf file in dependencies, got: " + str(elf)) |
| 241 | elf = elf[0] |
| 242 | |
| 243 | # Command to run the counter script and extract the min/max values. |
| 244 | out = ctx.actions.declare_file(ctx.attr.name + ".txt") |
| 245 | ctx.actions.run_shell( |
| 246 | outputs = [out], |
| 247 | inputs = [ctx.file._counter, elf], |
| 248 | command = "{} {} > {}".format(ctx.file._counter.path, elf.path, out.path), |
| 249 | ) |
| 250 | |
| 251 | runfiles = ctx.runfiles(files = ([out])) |
| 252 | return [DefaultInfo(files = depset([out]), runfiles = runfiles)] |
| 253 | |
Miguel Young de la Sota | 3b5a9f5 | 2022-03-24 16:11:42 -0400 | [diff] [blame] | 254 | otbn_library = rv_rule( |
Jade Philipoom | 39c9b32 | 2022-03-08 12:27:10 +0000 | [diff] [blame] | 255 | implementation = _otbn_library, |
Jade Philipoom | 39c9b32 | 2022-03-08 12:27:10 +0000 | [diff] [blame] | 256 | attrs = { |
| 257 | "srcs": attr.label_list(allow_files = True), |
Timothy Trippel | fc19734 | 2022-04-20 14:38:11 -0700 | [diff] [blame] | 258 | "_cc_toolchain": attr.label( |
| 259 | default = Label("@bazel_tools//tools/cpp:current_cc_toolchain"), |
| 260 | ), |
| 261 | "_otbn_as": attr.label( |
| 262 | default = "//hw/ip/otbn/util:otbn_as", |
| 263 | executable = True, |
| 264 | cfg = "exec", |
| 265 | ), |
Jade Philipoom | 39c9b32 | 2022-03-08 12:27:10 +0000 | [diff] [blame] | 266 | }, |
| 267 | fragments = ["cpp"], |
| 268 | toolchains = ["@rules_cc//cc:toolchain_type"], |
| 269 | incompatible_use_toolchain_transition = True, |
| 270 | ) |
| 271 | |
Miguel Young de la Sota | 3b5a9f5 | 2022-03-24 16:11:42 -0400 | [diff] [blame] | 272 | otbn_binary = rv_rule( |
Chris Frantz | 9b34e4a | 2021-11-24 17:03:12 -0800 | [diff] [blame] | 273 | implementation = _otbn_binary, |
Chris Frantz | 9b34e4a | 2021-11-24 17:03:12 -0800 | [diff] [blame] | 274 | attrs = { |
| 275 | "srcs": attr.label_list(allow_files = True), |
Jade Philipoom | 39c9b32 | 2022-03-08 12:27:10 +0000 | [diff] [blame] | 276 | "deps": attr.label_list(providers = [DefaultInfo]), |
Chris Frantz | 9b34e4a | 2021-11-24 17:03:12 -0800 | [diff] [blame] | 277 | "_cc_toolchain": attr.label(default = Label("@bazel_tools//tools/cpp:current_cc_toolchain")), |
Timothy Trippel | fc19734 | 2022-04-20 14:38:11 -0700 | [diff] [blame] | 278 | "_otbn_as": attr.label( |
| 279 | default = "//hw/ip/otbn/util:otbn_as", |
| 280 | executable = True, |
| 281 | cfg = "exec", |
| 282 | ), |
Timothy Trippel | fc19734 | 2022-04-20 14:38:11 -0700 | [diff] [blame] | 283 | "_otbn_data": attr.label( |
| 284 | default = "//hw/ip/otbn/data:all_files", |
| 285 | allow_files = True, |
| 286 | ), |
| 287 | "_wrapper": attr.label( |
Timothy Trippel | 024e393 | 2022-04-20 15:40:55 -0700 | [diff] [blame] | 288 | default = "//util:otbn_build", |
| 289 | executable = True, |
| 290 | cfg = "exec", |
Timothy Trippel | fc19734 | 2022-04-20 14:38:11 -0700 | [diff] [blame] | 291 | ), |
Chris Frantz | 9b34e4a | 2021-11-24 17:03:12 -0800 | [diff] [blame] | 292 | }, |
| 293 | fragments = ["cpp"], |
| 294 | toolchains = ["@rules_cc//cc:toolchain_type"], |
| 295 | incompatible_use_toolchain_transition = True, |
| 296 | ) |
Jade Philipoom | 6195eef | 2022-04-19 10:32:36 +0100 | [diff] [blame] | 297 | |
| 298 | otbn_sim_test = rv_rule( |
| 299 | implementation = _otbn_sim_test, |
| 300 | test = True, |
| 301 | attrs = { |
| 302 | "srcs": attr.label_list(allow_files = True), |
| 303 | "deps": attr.label_list(providers = [DefaultInfo]), |
| 304 | "_cc_toolchain": attr.label(default = Label("@bazel_tools//tools/cpp:current_cc_toolchain")), |
| 305 | "_otbn_as": attr.label( |
| 306 | default = "//hw/ip/otbn/util:otbn_as", |
| 307 | executable = True, |
| 308 | cfg = "exec", |
| 309 | ), |
| 310 | "_otbn_data": attr.label( |
| 311 | default = "//hw/ip/otbn/data:all_files", |
| 312 | allow_files = True, |
| 313 | ), |
| 314 | # TODO: make the simulator target an executable and update this |
| 315 | # dependency to match the others. |
| 316 | "_simulator": attr.label(default = "//hw/ip/otbn/dv/otbnsim:standalone.py", allow_single_file = True), |
| 317 | "_wrapper": attr.label( |
| 318 | default = "//util:otbn_build", |
| 319 | executable = True, |
| 320 | cfg = "exec", |
| 321 | ), |
| 322 | }, |
| 323 | fragments = ["cpp"], |
| 324 | toolchains = ["@rules_cc//cc:toolchain_type"], |
| 325 | incompatible_use_toolchain_transition = True, |
| 326 | ) |
Jade Philipoom | 6b746f7 | 2022-08-01 09:52:15 +0100 | [diff] [blame] | 327 | |
| 328 | otbn_consttime_test = rule( |
| 329 | implementation = _otbn_consttime_test_impl, |
| 330 | test = True, |
| 331 | attrs = { |
| 332 | "srcs": attr.label_list(allow_files = True), |
| 333 | "deps": attr.label_list(providers = [OutputGroupInfo]), |
| 334 | "subroutine": attr.string(), |
| 335 | "secrets": attr.string_list(), |
Jade Philipoom | 18a7479 | 2022-08-08 17:15:19 +0100 | [diff] [blame] | 336 | "initial_constants": attr.string_list(), |
Jade Philipoom | 6b746f7 | 2022-08-01 09:52:15 +0100 | [diff] [blame] | 337 | "_checker": attr.label( |
| 338 | default = "//hw/ip/otbn/util:check_const_time", |
| 339 | executable = True, |
| 340 | cfg = "exec", |
| 341 | ), |
| 342 | }, |
| 343 | ) |
Jade Philipoom | f05ed4d | 2022-07-28 17:27:21 +0100 | [diff] [blame] | 344 | |
| 345 | otbn_insn_count_range = rule( |
| 346 | implementation = _otbn_insn_count_range, |
| 347 | attrs = { |
| 348 | "deps": attr.label_list(providers = [OutputGroupInfo]), |
| 349 | "_counter": attr.label( |
| 350 | default = "//hw/ip/otbn/util:get_instruction_count_range.py", |
| 351 | allow_single_file = True, |
| 352 | ), |
| 353 | }, |
| 354 | ) |