blob: d843b3a5f430a84f068440323db43ea097a36feb [file] [log] [blame]
Dan McArdle411c7742022-08-02 18:26:40 -04001# Copyright lowRISC contributors.
2# Licensed under the Apache License, Version 2.0, see LICENSE for details.
3# SPDX-License-Identifier: Apache-2.0
4
5load("@lowrisc_opentitan//rules:rv.bzl", "rv_rule")
6
7def _opentitan_gdb_fpga_cw310_test(ctx):
8 test_script = '''#!/usr/bin/env bash
9 set -e
10
11 # Do not mask failures in the left-hand side of pipelines.
12 set -o pipefail
13
14 COLOR_RED='\\x1b[0;31m'
15 COLOR_GREEN='\\x1b[0;32m'
16 COLOR_PURPLE='\\x1b[0;35m'
17
18 function prefix_lines() {{
19 LABEL="$1"
20 COLOR="$2"
21 COLOR_RESET='\\x1b[m'
22 sed -Eu "s/(.*)/$COLOR[$LABEL]$COLOR_RESET \\1/"
23 }}
24
25 set -x
26
27 ./opentitantool load-bitstream --rom-kind=TestRom rom.bit
28
29 (openocd -f /usr/share/openocd/scripts/interface/ftdi/olimex-arm-usb-tiny-h.cfg \\
30 -c "adapter speed 500; transport select jtag; reset_config trst_and_srst" \\
31 -f {openocd_earlgrey_config} \\
32 |& prefix_lines OPENOCD "$COLOR_PURPLE") &
33 OPENOCD_PID=$!
34
35 # For debugging, it may be useful to use `--init-command`, which causes
36 # GDB to drop to the interactive prompt when the script ends rather than
37 # exiting.
38 (/tools/riscv/bin/riscv32-unknown-elf-gdb --command=script.gdb \\
39 |& prefix_lines GDB "$COLOR_GREEN") &
40
41 ./opentitantool console \\
42 --timeout 15s \\
43 --exit-success='{exit_success_pattern}' \\
44 |& prefix_lines CONSOLE "$COLOR_RED"
45
46 # Send TERM signal to OpenOCD and wait for all background jobs to complete. Note
47 # that GDB will exit naturally at the end of its script.
48 kill $OPENOCD_PID
49 wait
50 '''.format(
51 openocd_earlgrey_config = ctx.file._openocd_earlgrey_config.path,
52 exit_success_pattern = ctx.attr.exit_success_pattern,
53 )
54
55 # Write the GDB script to disk and load it with GDB's `--command` argument.
56 # This enables us to separate lines with whitespace, whereas if we piped the
57 # string into GDB's stdin, each newline would cause it to repeat the
58 # previous command.
59 gdb_script_file = ctx.actions.declare_file("{}.gdb".format(ctx.label.name))
60 test_script_file = ctx.actions.declare_file("{}.sh".format(ctx.label.name))
61
62 ctx.actions.write(output = gdb_script_file, content = ctx.attr.gdb_script)
63 ctx.actions.write(output = test_script_file, content = test_script)
64
65 # Construct a dict that we can pass to `ctx.runfiles()`, mapping symlink
66 # names to real file paths.
67 gdb_script_symlinks_flipped = {}
68 for label in ctx.attr.gdb_script_symlinks:
69 label_files = label.files.to_list()
70 if len(label_files) != 1:
71 fail("gdb_script_symlinks labels must have exactly one file, but", label, "has these files:", label_files)
72 gdb_script_symlinks_flipped[ctx.attr.gdb_script_symlinks[label]] = label_files[0]
73
74 gdb_script_runfiles = ctx.runfiles(
75 symlinks = gdb_script_symlinks_flipped,
76 files = gdb_script_symlinks_flipped.values(),
77 )
78 test_script_runfiles = ctx.runfiles(
79 # Relative paths provided by `File.path` seem to not work
80 # for generated files. Symlinking the runtime files wherever
81 # Bazel will run `test_script_file` sidesteps the issue.
82 symlinks = {
83 "opentitantool": ctx.file._opentitantool,
84 "rom.bit": ctx.file.rom_bitstream,
85 "script.gdb": gdb_script_file,
86 },
87 files = [
88 ctx.file._openocd_earlgrey_config,
89 ctx.file._opentitantool,
90 ctx.file.rom_bitstream,
91 gdb_script_file,
92 ],
93 )
94 runfiles = test_script_runfiles.merge(gdb_script_runfiles)
95
96 return [DefaultInfo(
97 executable = test_script_file,
98 runfiles = runfiles,
99 )]
100
101# Orchestrate opentitantool, OpenOCD, and GDB to load the given program into
102# SRAM and execute it in-place. This rule assumes that a CW310 FPGA and an
103# ARM-USB-TINY-H JTAG debugger are attached to the host.
104opentitan_gdb_fpga_cw310_test = rv_rule(
105 implementation = _opentitan_gdb_fpga_cw310_test,
106 attrs = {
107 "exit_success_pattern": attr.string(mandatory = True),
108 "gdb_script": attr.string(mandatory = True),
109 "gdb_script_symlinks": attr.label_keyed_string_dict(allow_files = True),
110 "rom_bitstream": attr.label(
111 mandatory = True,
112 allow_single_file = True,
113 ),
114 "_opentitantool": attr.label(
115 default = "//sw/host/opentitantool",
116 allow_single_file = True,
117 cfg = "exec",
118 ),
119 "_openocd_earlgrey_config": attr.label(
120 default = "//util/openocd/target:lowrisc-earlgrey.cfg",
121 allow_single_file = True,
122 ),
123 },
124 test = True,
125)