Skip to content

[otbnsim] Cycle-accurate Python model of Trivium/Bivium#29622

Open
andrea-caforio wants to merge 1 commit intolowRISC:masterfrom
andrea-caforio:trivium-python-model
Open

[otbnsim] Cycle-accurate Python model of Trivium/Bivium#29622
andrea-caforio wants to merge 1 commit intolowRISC:masterfrom
andrea-caforio:trivium-python-model

Conversation

@andrea-caforio
Copy link
Copy Markdown
Contributor

This commit introduces a cycle-accurate Python implementation of the Trivium primitive (see prim_trivium.sv) for the eventual replacement of the OTBN PRNG.

@andrea-caforio andrea-caforio self-assigned this Mar 30, 2026
@andrea-caforio andrea-caforio requested a review from a team as a code owner March 30, 2026 10:47
@andrea-caforio andrea-caforio requested review from rswarbrick and removed request for a team March 30, 2026 10:47
@andrea-caforio andrea-caforio requested review from a team, etterli and vogelpi March 30, 2026 10:47
@andrea-caforio andrea-caforio requested a review from h-filali March 30, 2026 10:51
Copy link
Copy Markdown
Contributor

@vogelpi vogelpi left a comment

Choose a reason for hiding this comment

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

Thanks @andrea-caforio , this looks mostly good. I have some minor comments regarding updating some indices.

We could also place this code under hw/ip/prim/util/ (because one could imagine using this also outside of OTBN sim). But I don't know if this would make integration into OTBN sim more complicated.

Copy link
Copy Markdown
Contributor

@etterli etterli left a comment

Choose a reason for hiding this comment

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

Thanks for this! It looks great. I have some questions (probably because I don't understand Trivium very well) and some NITs.

Regarding moving this into hw/ip/prim/util/:
We can do this, it is not a problem when integrating it into the OTBN sim. Other parts of the OTBN sim already depend on external python parts. See for example ext_regs.py. The dependency must simply be defined in the bazel file (see here).

I would suggest that the URND in OTBN sim instantiates a Trivium/Bivium object and implements the required wrapper logic.

# Every seed operation fills a chunk of predefined size of the state
# starting with the least significant region until every bit of the state
# has been seeded. The seed operations can be interspersed with update
# invocations such that keystream and seeding can take place concurrently.
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Question about Trivium: Does this mean that we can generate usable (for e.g. masking) randomness while re-seeding the trivium PRNG? So we do not have to wait the initial 64 cycles before we get randomness?

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Ah thanks to your nice description below I think this means that we can continue using the old state to generate a keystream but at the same time feed in a new seed. And once we have fully reseeded it, the keystream produces value based upon the new seed?

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

Exactly, Bivium will be seeded in 6 32-bit` chunks that make it possible to seed while updating at the same time.

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Please note that this works if the output width is greater than the width of the smallest shift register internally. For Bivium, this is 84 bits.

What also helps is that there is always a little delay (IIRC 6 clock cycles) between two subsequent 32-bit words for reseeding as there is CDC crossing on the EDN interface. So in practice we will do 6 updates between to seed words. The first seed word will have propagated into most of the state after this already.

In the header of hw/ip/prim/rtl/prim_trivium.sv I gave more insight on this matter.

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Thanks for the explanations. Maybe worth to point to this additional info?

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

I expanded the comment.

@andrea-caforio andrea-caforio force-pushed the trivium-python-model branch 3 times, most recently from 454d268 to d36ae98 Compare March 31, 2026 11:42
@andrea-caforio
Copy link
Copy Markdown
Contributor Author

Thank you @vogelpi and @etterli for the thorough reviews. I addressed the points and moved the file to hw/ip/prim/util.

Copy link
Copy Markdown
Contributor

@vogelpi vogelpi left a comment

Choose a reason for hiding this comment

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

Thanks for addressing my comments @andrea-caforio ! This LGTM modulo the comments of @etterli .

# Every seed operation fills a chunk of predefined size of the state
# starting with the least significant region until every bit of the state
# has been seeded. The seed operations can be interspersed with update
# invocations such that keystream and seeding can take place concurrently.
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Please note that this works if the output width is greater than the width of the smallest shift register internally. For Bivium, this is 84 bits.

What also helps is that there is always a little delay (IIRC 6 clock cycles) between two subsequent 32-bit words for reseeding as there is CDC crossing on the EDN interface. So in practice we will do 6 updates between to seed words. The first seed word will have propagated into most of the state after this already.

In the header of hw/ip/prim/rtl/prim_trivium.sv I gave more insight on this matter.

Copy link
Copy Markdown
Contributor

@etterli etterli left a comment

Choose a reason for hiding this comment

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

Thank you for the update! I only have some minor stuff like replacing all instances of clock() with step() etc.

# Every seed operation fills a chunk of predefined size of the state
# starting with the least significant region until every bit of the state
# has been seeded. The seed operations can be interspersed with update
# invocations such that keystream and seeding can take place concurrently.
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Thanks for the explanations. Maybe worth to point to this additional info?

This commit introduces a cycle-accurate Python implementation of the
Trivium primitive (see `prim_trivium.sv`) for the eventual replacement
of the OTBN PRNG.

Signed-off-by: Andrea Caforio <andrea.caforio@lowrisc.org>
@etterli etterli added the CI:Rerun Rerun failed CI jobs label Apr 1, 2026
@github-actions github-actions bot removed the CI:Rerun Rerun failed CI jobs label Apr 1, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants