Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Fix OTP bitstream splicing #15163

Merged
merged 5 commits into from Oct 19, 2022
Merged

Conversation

dmcardle
Copy link
Contributor

@dmcardle dmcardle commented Sep 27, 2022

A series of miracles occurred on Friday, enabling me to deduce how updatemem interprets its input and how Vivado lays out data in the BRAMs. With these changes, I can splice OTP values into a bitstream and observe the result in a GDB test! (Now we can disable ROM execution for the SRAM GDB test and drop the flaky tag!)

I think that OTP splicing never worked. To prevent regressions, I think I'll write an "OTP dumper" functest. We can instantiate the functest a few times with a variety of OTP-spliced bitstreams and assert that it prints the expected values.

Fixes #15162
Fixes #15174

@dmcardle dmcardle force-pushed the dmcardle/fix-otp-splice branch 8 times, most recently from bd05906 to fbdc515 Compare October 17, 2022 15:45
@dmcardle dmcardle changed the title WIP changing OTP splicing logic. See lowRISC/opentitan#15162 Fix OTP bitstream splicing Oct 17, 2022
@dmcardle dmcardle marked this pull request as ready for review October 17, 2022 15:58
Copy link
Contributor

@a-will a-will left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Nice work! I put in some nits about generalizing scripts, but that probably doesn't have to be in this PR.

@@ -102,6 +91,24 @@ filegroup(
}),
)

[
filegroup(
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Can you add a "manual" tag to these filegroups? That way, Vivado-dependent targets won't get picked up by wildcards.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Done. I added to the other filegroups as well. I think that this hasn't been an issue because these targets aren't tests.

hw/ip/rom_ctrl/util/gen_vivado_mem_image.py Show resolved Hide resolved
# The scrambled Boot ROM is actually 39 bits wide but the updatemem tool segfaults
# for slice sizes not divisible by 8.
if {[expr {($slice_end - $slice_begin + 1) < 8}]} {
if {$filename eq "rom.mmi" && [expr {($slice_end - $slice_begin + 1) < 8}]} {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

nit: This hard-coded file name key is awkward. Is there an argument we can add that would specifically point to a different desired behavior for this process? (i.e. something that doesn't require knowing the function of the memory but instead describes how the collection of BRAMs should be processed)

At the top level, we'll have the top-specific stuff hard-coded, but this script will be more readily reused if we don't automatically push those all the way to the leaf processes.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Honestly, I don't understand why we're messing with slice_end for rom.mmi. This filename check was just meant to preserve the existing behavior for the ROM.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It kind of looks like we're lying to updatemem and saying that the bitlanes cover 40 bits when they actually cover 39. I wonder if this was because you can't write 39 bits with 10 hex digits. Maybe this special case for ROM would not be necessary if we wrote four 39-bit words at a time (39 hex digits)?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

OK, I've generalized this a bit and it's no longer dependent on the filename. These changes are contained in the new commit, [fpga] Refactor quirks in MMI file generator. PTAL!

rules/splice.bzl Outdated Show resolved Hide resolved
I discovered a few problems with the OTP-specific MMI files we have been
generating prior to this commit.

(1) The file's bitlanes were overlapping. For instance, the first
bitlane claimed to cover bits 0-3 (inclusive) and the second one claimed
to cover bits 1-4. This is expressly not allowed by Vivado's updatemem
manual, so I knew something was wrong. By poking around the Vivado GUI,
I realized that OTP bitlanes should each cover a single bit. I'm not
sure whether that logic is correct or necessary for the ROM case, so I
left it alone.

(2) The MMI file claimed that BRAMS are the type "RAMB32" when the OTP
BRAMs are actually RAMB18E1. It's not as simple as just saying "RAMB18"
in the MMI file. Ultimately, I got it working after bumping the MMI's
minor version from 0 to 1 and configuring an environment variable before
calling updatemem.

(3) The bitlane "Placement" attributes were all wrong because we were
trying to trim the "RAMB36_" prefix from strings that actually began
with "RAMB18_".

(4) The AddressSpace and and DataWidth tags had inaccurate values.
Apparently there is a significant amount of padding between OTP words in
the OTP BRAMs. In fact, each word is followed by 15 zeroes.

Separately, I also modified the TCL script to dump the OTP BRAMs'
INIT_XX strings to a text file. Ultimately, examining these INIT_XX
strings helped me crack the way that Vivado lays out data in the
BRAMs (more detail in a later commit). However, examining the INIT_XX
strings in the Vivado GUI required too much clicking; there are 64
INIT_XX strings per OTP BRAM, and there are 22 BRAMs. This is purely a
debugging aid, but it only takes a few seconds to generate.

Signed-off-by: Dan McArdle <dmcardle@google.com>
Copy link
Contributor Author

@dmcardle dmcardle left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Ready for another look :)

# The scrambled Boot ROM is actually 39 bits wide but the updatemem tool segfaults
# for slice sizes not divisible by 8.
if {[expr {($slice_end - $slice_begin + 1) < 8}]} {
if {$filename eq "rom.mmi" && [expr {($slice_end - $slice_begin + 1) < 8}]} {
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

OK, I've generalized this a bit and it's no longer dependent on the filename. These changes are contained in the new commit, [fpga] Refactor quirks in MMI file generator. PTAL!

hw/ip/rom_ctrl/util/gen_vivado_mem_image.py Show resolved Hide resolved
dmcardle added a commit to dmcardle/opentitan that referenced this pull request Oct 18, 2022
I noticed that a few unit test targets outside of //sw/... were not
running on CI.

This commit ensures that CI runs the following additional targets:
* //hw/ip/rom_ctrl/util:gen_vivado_mem_image_test (after lowRISC#15163 merges)
* //rules/scripts:bitstreams_workspace_test
* //util:generate_compilation_db_test

Signed-off-by: Dan McArdle <dmcardle@google.com>
dmcardle added a commit to dmcardle/opentitan that referenced this pull request Oct 18, 2022
I noticed that a few unit test targets outside of //sw/... were not
running on CI.

This commit ensures that CI runs the following additional targets:
* //hw/ip/rom_ctrl/util:gen_vivado_mem_image_test (after lowRISC#15163 merges)
* //rules/scripts:bitstreams_workspace_test
* //util:generate_compilation_db_test

Signed-off-by: Dan McArdle <dmcardle@google.com>
Rather than enabling quirks based on filename, this commit adds
parameters to the `generate_mmi` proc. This also simplifies the
interface a bit and improves documentation.

Signed-off-by: Dan McArdle <dmcardle@google.com>
This script reads MEM files that can be read by Verilog's $readmemh and
produces a MEM file that `updatemem` will understand. It turns out that
the transformation for ROM data was not right for OTP data due to
differences in the underlying hardware. This caught me by surprise
because updatemem was exiting successfully.

By comparing //hw/ip/otp_ctrl/data:img_rma, which is passed directly to
Vivado, with the INIT_XX strings that Vivado produces, I was able to
determine the transformation. This commit also includes a few features
that I used to bootstrap my understanding: (1) a function that reads
INIT_XX strings from OTP BRAMs and produces their memory content and (2)
a mocked out updatemem "simulator" that takes hex strings as input and
produces the same INIT_XX lines that the real updatemem would.

I used a modified version of the sram_program GDB test[0] to dump
relevant sections of OTP memory and verify that the OTP values I
modified can actually be read from OTP memory.

[0]: //sw/device/examples/sram_program:sram_program_fpga_cw310

Signed-off-by: Dan McArdle <dmcardle@google.com>
The new OTP image sets CREATOR_SW_CFG_ROM_EXEC_EN to zero.

This commit also adds the get_otp_images() macro to //rules/otp.bzl,
which aims to keep OTP splicing targets in //hw/bitstream and
//hw/bitstream/vivdao in sync with OTP image definitions.

Signed-off-by: Dan McArdle <dmcardle@google.com>
Now that execution is disabled, OpenOCD connection should not be flaky
anymore! This should fix lowRISC#15174.

Signed-off-by: Dan McArdle <dmcardle@google.com>
@dmcardle
Copy link
Contributor Author

Whoops, looks like I introduced a division-by-zero error in the CW305 build because there are no OTP cells. https://dev.azure.com/lowrisc/opentitan/_build/results?buildId=97760&view=logs&j=4bc87d6f-5c28-5789-95a2-5c084ae7a0b2&t=054949bd-ad52-58ee-5229-51b7a2cd10e0&l=17991

INFO: [1-1] Dumping MMI to rom.mmi
INFO: [1-4] MMI dumped to /azp/agent/_work/1/a/build-out/hw/synth-vivado/rom.mmi
WARNING: [Vivado 12-180] No cells matched 'get_cells -hierarchical -filter { PRIMITIVE_TYPE =~ BMEM.bram.* && NAME =~ *u_otp_ctrl*}'.
INFO: [2-1] Dumping MMI to otp.mmi
divide by zero
sourcing script /azp/agent/_work/1/a/build-out/hw/synth-vivado/vivado_hook_write_bitstream_pre.tcl failed

Just pushed a fix — returning early from the TCL proc when there are no BRAMs.

Copy link
Contributor

@alphan alphan left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks @dmcardle! Since this is such a substantial improvement over the level of OTP splicing support we have right now, which is none :), and since this will unblock several tests, let's get this merged as soon as CI is green. We can improve this incrementally as needed. Also, IIRC @milesdai was working on OTP overlays. We can look into simplifying the new OTP definitions once this is merged.

@dmcardle dmcardle added the Status:Ready to merge PR is ready to be merged by a committer. label Oct 19, 2022
@dmcardle
Copy link
Contributor Author

CI passed!

@drewmacrae drewmacrae merged commit f800b33 into lowRISC:master Oct 19, 2022
dmcardle added a commit to dmcardle/opentitan that referenced this pull request Oct 19, 2022
I noticed that a few unit test targets outside of //sw/... were not
running on CI.

This commit ensures that CI runs the following additional targets:
* //hw/ip/rom_ctrl/util:gen_vivado_mem_image_test (after lowRISC#15163 merges)
* //rules/scripts:bitstreams_workspace_test
* //util:generate_compilation_db_test

Signed-off-by: Dan McArdle <dmcardle@google.com>
dmcardle added a commit to dmcardle/opentitan that referenced this pull request Oct 19, 2022
I noticed that a few unit test targets outside of //sw/... were not
running on CI.

This commit ensures that CI runs the following additional targets:
* //hw/ip/rom_ctrl/util:gen_vivado_mem_image_test (after lowRISC#15163 merges)
* //rules/scripts:bitstreams_workspace_test
* //util:generate_compilation_db_test

Signed-off-by: Dan McArdle <dmcardle@google.com>
drewmacrae pushed a commit that referenced this pull request Oct 20, 2022
I noticed that a few unit test targets outside of //sw/... were not
running on CI.

This commit ensures that CI runs the following additional targets:
* //hw/ip/rom_ctrl/util:gen_vivado_mem_image_test (after #15163 merges)
* //rules/scripts:bitstreams_workspace_test
* //util:generate_compilation_db_test

Signed-off-by: Dan McArdle <dmcardle@google.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Component:FPGA FPGA related issues Status:Ready to merge PR is ready to be merged by a committer. SW:Build System
Projects
None yet
Development

Successfully merging this pull request may close these issues.

Improve robustness of OpenOCD connection in SRAM execution tests Fix OTP splicing with updatemem
4 participants