Skip to content

[opentitantool] Add support for writing (& verifying) memories via the FPGA bkdr_loader#30477

Draft
AlexJones0 wants to merge 11 commits into
lowRISC:masterfrom
AlexJones0:bkdr_loader_writes
Draft

[opentitantool] Add support for writing (& verifying) memories via the FPGA bkdr_loader#30477
AlexJones0 wants to merge 11 commits into
lowRISC:masterfrom
AlexJones0:bkdr_loader_writes

Conversation

@AlexJones0

Copy link
Copy Markdown
Contributor

Note: this PR is a draft because it depends on #30473, #30474 and #30475. The first 3 commits of this PR are from #30473, the 4th-6th commits are from #30474, the 7th commit is from #30475 and only the 8th-11th commits are relevant for review. Once #30473, #30474 and #30475 are merged, this PR will be marked as ready for review.

Note that these commands will not work until the RTL fix in #30471 has been merged. Note also that the ROM endpoint is currently disabled for now to allow bitstream splicing flows to continue working.

Implement FPGA backdoor loader memory write operations via OpenTitanLib / OpenTitanTool. Adds three new commands:

  • Using the opentitantool bkdr write command, you can write to target memories via the backdoor loader (when it is in its preloading mode, entered via bkdr enter). Options are available for customizing the offset of the write, and for whether to read back written data and verify the write (which can be much slower). 3 input formats are supported:
    • hex - hex words given as arguments over stdin.
    • clear - clear some portion or the entirety of a target's memory with a byte pattern.
    • vmem - load data from a VMEM file and write that to the target memory. For now, these are assumed to always have a stride of 1 word per address.
  • The opentitantool bkdr verify command is almost identical to bkdr write, except it does not actually write the data. It instead takes the same inputs and only does the readback verification.
  • The opentitantool bkdr batch command is an "orchestrator" that batches multiple VMEM writes. This is needed because a common use case for FPGA testing will be to splice multiple memories (e.g. ROM, OTP, potentially flash in the future). If these are all separate bkdr write commands, OpenTitanTool will spin up a separate OpenOCD instance each time, which will add some non-insignificant overheads to these operations. By batching we can amortize these overheads. However, clap does not naturally support nested/chained subcommands, and as such for now we implement a subset of write operations (only VMEM writes for now).

One difficulty with the bkdr_loader operations is that they can be somewhat slow, as they can require many DMI writes and reads over JTAG. The current implementation for DMI writes is particularly inefficient for the case where we have multiple writes in a row -- as is required to write to a target's memory via the bkdr_loader -- so an optimized batched writing interface is added to the Dmi trait, with a custom implementation for OpenOCD.

The existing VMEM implementation assumed that VMEMs would always contain
32 bit words, and that we always want to interpret the VMEM with byte
address strides. This is true for the existing use case of SRAM
programming, but will not be true if we want to load other VMEMs onto
the FPGA such as the scrambled ROM or OTP configurations, which have
39- and 22-bit word sizes respectively and both use word address strides
in their VMEM files.

Update the VMEM model and VMEM parsing logic so that we now store
Vec<Word> instead of Vec<u32>, where a Word is essentially just a
Vec<u8> of bytes stored in Big Endian order. Likewise, make VMEM parsing
and addressing logic consume an address stride argument, so that we know
how we should traverse VMEM addresses when e.g. merging sections or
enumerating the various data-address pairs.

Finally, this changes the existing VMEM consumer (load_sram_program) to
make use of these changes.

Signed-off-by: Alex Jones <alex.jones@lowrisc.org>
Add VMEM parsing tests related to the newly introduced address stride
and arbitrary sized word features. Also extend existing test coverage to
features that were not previously tested, such as the merging of
contiguous VMEM sections.

Signed-off-by: Alex Jones <alex.jones@lowrisc.org>
Signed-off-by: Alex Jones <alex.jones@lowrisc.org>
Signed-off-by: Alex Jones <alex.jones@lowrisc.org>
When we're doing lots of DMI operations, these become very noisy. They
make much more sense to exist at a "Debug" logging level.

Signed-off-by: Alex Jones <alex.jones@lowrisc.org>
This commit implements the initial logic for integrating the FPGA
backdoor loader into OpenTitanLib & OpenTitanTool. It provides
interfaces for connecting to the bkdr_loader TAP via OpenOCD, entering
the backdoor loader (applying the TAP strapping and resetting), and for
enumerating/discovering the target information from the CSRs.

A new `opentitantool bkdr` command is implemented for using this
functionality, with 3 subcommands - `enter` to enter the backdoor
loader, `exit` to finish using it and take OT out of reset, and `info`
to list info about the available targets (or a specific target). As part
of this, there is some logic for looking up a target by its unique ID.

Note that we return handles for each of the different targets which
simply wrap the `BackdoorTargetInfo` - these will be extended in future
commits to allow operations on the various targets.

Signed-off-by: Alex Jones <alex.jones@lowrisc.org>
Add a `bkdr read` command to OpenTitanTool / OpenTitanLib which can be
used to read from target memories via the backdoor loader (when it is in
its preloading mode, entered via `bkdr enter`).

Options are available for customizing the offset & size of the read, as
well as to output the data in raw/hex/VMEM formats.

Signed-off-by: Alex Jones <alex.jones@lowrisc.org>
This behaviour can technically be replicated by first using
`opentitantool fpga clear-bitstream` and then `opentitantool fpga
load-bitstream`, but this is less convenient - this new `--force`
option acts as a convenience helper.

This is more important when using the FPGA bkdr_loader flow which can
change the FPGA memory contents without changing the bitstream
USR_ACCESS value.

Signed-off-by: Alex Jones <alex.jones@lowrisc.org>
This commit introduces a `batched_dmi_writes` method to the `DMI` trait,
which implementers can override to provide optimized implementations
that batch multiple sequential DMI writes, without caring about reading
out the returned values.

This will be a particular pain point for interaction with the
DMI in the FPGA bkdr_loader, and as such optimizing these writes can
potentially give us a 5x speedup by reducing the number of JTAG
transactions and the amount of idle time spent waiting for results
(i.e. for reducing the overhead of each write).

Signed-off-by: Alex Jones <alex.jones@lowrisc.org>
Add a `bkdr write` command to OpenTitanTool / OpenTitanLib which can be
used to write to target memories via the backdoor loader (when it is in
its preloading mode, entered via `bkdr enter`).

Options are available for customizing the offset and read and whether
readbacks & status checks are implemented for verifying the write (which
takes much longer, due to the various optimizations that are possible
when writing but not when reading).

3 different input formats are supported - hex (as args to the command),
clear (clear some number of words with a given repeated byte pattern),
and vmem (as a path to some VMEM file). This should be enough to support
a variety of use cases - writing VMEMs of the scrambled ROM and OTP
images, clearing some target's memory, and manually modifying specific
memory values via fine-grained commands.

A `bkdr verify` command is added - this is basically the same as `bkdr
write --verify`, but without doing the actual write operation. The
intention is that you can read and verify that the contents of some
memory matches your input, without needing to perform any write
operation beforehand, or deal with the manual comparison logic yourself
outside of OpenTitanTool after reading.

Signed-off-by: Alex Jones <alex.jones@lowrisc.org>
Adds a `bkdr batch` command to OpenTitanTool / OpenTitanLib which can be
used to batch multiple write operations to target memories via the
backdoor loader (when it is in its preloading mode, entered via `bkdr
enter`).

This command exists despite the presence of `opentitantool --exec` to
reduce OpenOCD overhead from repeated writes. We may want to load many
images onto the FPGA (e.g. ROM, OTP, flash), and for each opentitantool
command a new instance of OpenOCD will be spawned and connected to the
backdoor TAP. Rather than incur this heavy overhead, we can spawn
OpenOCD once and batch together all of the writes.

Due to the added complexity of dealing with nested/chained sub-commands,
a limited subset of write options are supported here (only VMEM formats
for now). You can still choose to `--verify`, but this will apply to all
writes that are completed. There is also a `--start` option which will
perform `bkdr exit` for you, since that command would also require an
additional OpenOCD instantiation which we would like to eliminate.

Signed-off-by: Alex Jones <alex.jones@lowrisc.org>
@AlexJones0 AlexJones0 requested a review from a team as a code owner June 19, 2026 18:43
@AlexJones0 AlexJones0 requested review from cfrantz and removed request for a team June 19, 2026 18:43
@AlexJones0 AlexJones0 marked this pull request as draft June 19, 2026 18:44
@AlexJones0 AlexJones0 requested review from engdoreis, jwnrt and pamaury and removed request for cfrantz June 19, 2026 18:44
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant