Skip to content

[prim,doc] Updated the main documentation for the post primgen world #27422

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

Open
wants to merge 3 commits into
base: master
Choose a base branch
from

Conversation

HU90m
Copy link
Member

@HU90m HU90m commented Jun 12, 2025

This updates the documentation to how primitives are expected to be used.

The documentation doesn't cover the temporary use of a partner:prim_tech:all and the virtual prim_pkg. I think the former could potentially be phased out with a commit in this PR removing lines like fileset_partner ? (partner:prim_tech:all). Unless I'm missing something?

As prim_pkg may be hanging around a little longer than we'd like. A paragraph could be added in a follow up PR explaining how to provide your own prim_pkg as a stop gap. Effort would probably be better spent transitioning away from it rather than documenting it, lest it become an immortal temporary solution.

@andreaskurth andreaskurth linked an issue Jun 12, 2025 that may be closed by this pull request
1 task
@andreaskurth
Copy link
Contributor

Thanks @HU90m! This would address issue #27372, right? (I've just linked that; please unlink if not appropriate.)

HU90m added 3 commits June 14, 2025 07:27
Primitives are slightly different to your usual hw blocks.
They should probably be given their own higher level heading,
like cores have.

Also, sorted so that they are in alphabetical order.

Signed-off-by: Hugo McNally <hugo.mcnally@gmail.com>
The style guide asks that text be one sentence per line,
for clearer diffs.
Changing this before planned future edits.

Signed-off-by: Hugo McNally <hugo.mcnally@gmail.com>
This brings the documentation up to date with how primitives now work
and are used.

Signed-off-by: Hugo McNally <hugo.mcnally@gmail.com>
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.

Just a bunch of nits. Thanks for writing this!

* Primitives with a single, generic, implementation are normal SystemVerilog modules inside the `hw/ip/prim/rtl` directory.
We call these primitives *technology-independent primitives*.
* Primitives with multiple implementations are called *technology-dependent primitives*.
Each implementation has it's own directory within `hw/ip/` with the prefix `prim`, e.g. `hw/ip/prim_generic/` or `hw/ip/prim_xilinx/`.
Copy link
Contributor

Choose a reason for hiding this comment

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

nit:

Suggested change
Each implementation has it's own directory within `hw/ip/` with the prefix `prim`, e.g. `hw/ip/prim_generic/` or `hw/ip/prim_xilinx/`.
Each implementation has its own directory within `hw/ip/` with the prefix `prim`, e.g. `hw/ip/prim_generic/` or `hw/ip/prim_xilinx/`.

properties:
Collections of technology-dependent primitives are called technology libraries.
The *generic* technology library contains a pure-SystemVerilog implementation of primitives' functionality.
It's is commonly used for simulations and as functional reference.
Copy link
Contributor

Choose a reason for hiding this comment

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

nit:

Suggested change
It's is commonly used for simulations and as functional reference.
This library is commonly used for simulations and as functional reference.


Technology libraries collect implementations of primitives.
To allow hardware blocks to be generic across implementations of *technology-dependent primitives*, a feature of FuseSoC called *[virtual cores][]* are used.*
Copy link
Contributor

Choose a reason for hiding this comment

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

nit: feature is singular

Suggested change
To allow hardware blocks to be generic across implementations of *technology-dependent primitives*, a feature of FuseSoC called *[virtual cores][]* are used.*
To allow hardware blocks to be generic across implementations of *technology-dependent primitives*, a feature of FuseSoC called *[virtual cores][]* is used.*

Copy link
Contributor

Choose a reason for hiding this comment

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

👍, and I think the * at the end should be removed.


Technology libraries collect implementations of primitives.
To allow hardware blocks to be generic across implementations of *technology-dependent primitives*, a feature of FuseSoC called *[virtual cores][]* are used.*
These can be thought of as similar to virtual methods in C++ or SystemVerilog.
Copy link
Contributor

Choose a reason for hiding this comment

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

Before this line, we might want to describe what it means to a hardware design engineer, hehe. For example...

Suggested change
These can be thought of as similar to virtual methods in C++ or SystemVerilog.
Any implementation of a virtual core must provide the same functionality and interface.
The module name must be the same, and the parameter and port lists must include all the required members of the interface.
For an analog, virtual cores can be thought of as similar to virtual methods in C++ or SystemVerilog.

Copy link
Contributor

Choose a reason for hiding this comment

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

Maybe 'analogy' or 'analogon'? ('Analog' always feels itchy to the digital designer in me 😉)

which contains a pure-SystemVerilog implementation of the functionality. This
library is commonly used for simulations and as functional reference. The
`generic` technology library is contained in the `hw/ip/prim_generic` directory.
To find the interface of a given virtual primitive look at it's generic implementation in `hw/prim_generic/`.
Copy link
Contributor

Choose a reason for hiding this comment

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

nit:

Suggested change
To find the interface of a given virtual primitive look at it's generic implementation in `hw/prim_generic/`.
To find the interface of a given virtual primitive look at its generic implementation in `hw/prim_generic/`.


If you'd like to depend on a specific implementation, you can add the specific implementation's VLNV instead of the virtual VLNV.
For example, you would depend on `lowrisc:prim_xilinx:prim_fifo_sync` instead of `lowrisc:prim:prim_fifo_sync` if you wanted to forcefully use the Xilinx implementation.
**This is not recommended.**
Copy link
Contributor

Choose a reason for hiding this comment

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

nit: Best to provide a reason alongside recommendations.

Suggested change
**This is not recommended.**
Because this method can restrict the flexibility to swap compatible cores, **this is not recommended.**

You can rely on the generic implementation or even another library's implementation for other primitives.

Technology libraries don't have to live in the OpenTitan repository.
If they are not in the OpenTitan repository, you need to make sure the path to them is given to FuseSoC with either an additional `--core-root=` argument or set in `fusesoc.conf`.
Copy link
Contributor

Choose a reason for hiding this comment

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

nit:

Suggested change
If they are not in the OpenTitan repository, you need to make sure the path to them is given to FuseSoC with either an additional `--core-root=` argument or set in `fusesoc.conf`.
If they are not in the OpenTitan repository, you need to make sure the path to them is given to FuseSoC with either an additional `--cores-root=` argument or set in `fusesoc.conf`.


### Selecting a technology library

You can select a technology library one of two ways.
Copy link
Contributor

Choose a reason for hiding this comment

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

nit:

Suggested change
You can select a technology library one of two ways.
You can select a technology library in one of two ways.


You can select a technology library one of two ways.

If you have your own invokable core which requires a particular primitive, you should add the technology library's VLNV to it's dependencies.
Copy link
Contributor

Choose a reason for hiding this comment

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

nit:

Suggested change
If you have your own invokable core which requires a particular primitive, you should add the technology library's VLNV to it's dependencies.
If you have your own invokable core which requires a particular primitive, you should add the technology library's VLNV to its dependencies.


If you have your own invokable core which requires a particular primitive, you should add the technology library's VLNV to it's dependencies.
`hw/top_earlgrey/chip_earlgrey_cw310.core` is an example of an invokable core requiring a particular technology library, namely `lowrisc:prim_xilinx:all`.
You'll notice this VLNV in it's dependencies.
Copy link
Contributor

Choose a reason for hiding this comment

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

nit:

Suggested change
You'll notice this VLNV in it's dependencies.
You'll notice this VLNV in its dependencies.

```

Notice that there aren't xilinx specific implementations for all primitives, so the generic implementation is requested.
Copy link
Contributor

Choose a reason for hiding this comment

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

Suggested change
Notice that there aren't xilinx specific implementations for all primitives, so the generic implementation is requested.
Notice that there aren't Xilinx specific implementations for all primitives, so the generic implementation is requested.

Copy link
Contributor

@andreaskurth andreaskurth left a comment

Choose a reason for hiding this comment

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

Couple of comments, but overall LGTM. Thanks @HU90m!

Also, edit the description to better describe the specific implementation.
4. For every primitive implemented by your library:
1. Copy across the generic implementation into your library, e.g. `mv hw/ip/prim_generic/rtl/prim_flop.sv hw/ip/prim_mytech/rtl/prim_flop.sv`.
2. Make your changes to the implementation without modifying the module ports or removing parameters.
Copy link
Contributor

Choose a reason for hiding this comment

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

Suggested change
2. Make your changes to the implementation without modifying the module ports or removing parameters.
2. Make your changes to the implementation without modifying the module ports or parameter declarations.

Because I don't think adding parameters would work? And I added "declarations" because otherwise people might be confused that they cannot change parameter values.

Copy link
Contributor

Choose a reason for hiding this comment

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

Adding parameters can work in specific circumstances (e.g. somewhere defparam is accepted or where you know there is a specific implementation), but most of the time, it doesn't.

Change the vendor and name in this file, e.g. `lowrisc:prim_generic` would become `partner:mytech` where your organisation's name can be used in the place of 'partner'.
Also, edit the description to better describe the specific implementation.
4. For every primitive implemented by your library:
1. Copy across the generic implementation into your library, e.g. `mv hw/ip/prim_generic/rtl/prim_flop.sv hw/ip/prim_mytech/rtl/prim_flop.sv`.
Copy link
Contributor

Choose a reason for hiding this comment

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

Suggested change
1. Copy across the generic implementation into your library, e.g. `mv hw/ip/prim_generic/rtl/prim_flop.sv hw/ip/prim_mytech/rtl/prim_flop.sv`.
1. Copy across the generic implementation into your library, e.g. `cp hw/ip/prim_generic/rtl/prim_flop.sv hw/ip/prim_mytech/rtl/prim_flop.sv`.

Unless you've aliased mv to cp? 😉

4. For every primitive implemented by your library:
1. Copy across the generic implementation into your library, e.g. `mv hw/ip/prim_generic/rtl/prim_flop.sv hw/ip/prim_mytech/rtl/prim_flop.sv`.
2. Make your changes to the implementation without modifying the module ports or removing parameters.
3. Copy the generic primitive's core description into your library, e.g. `mv hw/ip/prim_generic/prim_generic_flop.core hw/ip/prim_mytech/prim_mytech_flop.core`.
Copy link
Contributor

Choose a reason for hiding this comment

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

Suggested change
3. Copy the generic primitive's core description into your library, e.g. `mv hw/ip/prim_generic/prim_generic_flop.core hw/ip/prim_mytech/prim_mytech_flop.core`.
3. Copy the generic primitive's core description into your library, e.g. `cp hw/ip/prim_generic/prim_generic_flop.core hw/ip/prim_mytech/prim_mytech_flop.core`.

4. Edit this copied primitive core file so that it has the new primitive library name, e.g. replacing `lowrisc:prim_generic:flop` with `partner:prim_mytech:flop`.
5. Then in the libraries main core file, e.g. `hw/ip/prim_mytech/prim_mytech.core`, replace all instances of the generic implementation with your specific implementation, e.g. replacing `lowrisc:prim_generic:flop` with `partner:prim_mytech:flop` again.

You don't have to have your own implementation for every primitive.
Copy link
Contributor

Choose a reason for hiding this comment

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

Depending on the use case / requirements of the implementation, there are some requirements on the prim implementation. For example, if you care about security against physical attacks, you need to constrain the tools you're using to not remove a prim_buf. This isn't (and shouldn't be) part of the generic implementation. Should we create an issue to add documentation on this topic?

```sh
fusesoc --cores-root=$OT_REPO run \
--flag fileset_partner \
--mapping partner:prim_mytech:all
Copy link
Contributor

Choose a reason for hiding this comment

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

Suggested change
--mapping partner:prim_mytech:all
--mapping partner:prim_mytech:all \

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.

[doc] Prim libraries & primgen documentation is outdated
3 participants