-
Notifications
You must be signed in to change notification settings - Fork 858
[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
base: master
Are you sure you want to change the base?
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change | ||||||||||||||||||||
---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
|
@@ -32,198 +32,165 @@ | |||||||||||||||||||||
|
||||||||||||||||||||||
## Concepts | ||||||||||||||||||||||
|
||||||||||||||||||||||
This directory contains basic building blocks to create a hardware design, | ||||||||||||||||||||||
called primitives. A primitive is described by its name, and has a well-defined | ||||||||||||||||||||||
list of ports and parameters. | ||||||||||||||||||||||
This directory contains basic building blocks to create a hardware design, called primitives. | ||||||||||||||||||||||
A primitive is described by its name, and has a well-defined list of ports and parameters. | ||||||||||||||||||||||
|
||||||||||||||||||||||
Under the hood, primitives are slightly special, as they can have multiple | ||||||||||||||||||||||
implementations. In contrast to many other modules in a hardware design, | ||||||||||||||||||||||
primitives must often be implemented in technology-dependent ways. For example, | ||||||||||||||||||||||
a clock multiplexer for a Xilinx FPGA is implemented differently than one for | ||||||||||||||||||||||
a specific ASIC technology. | ||||||||||||||||||||||
Under the hood, primitives are slightly special, as they can have multiple implementations. | ||||||||||||||||||||||
In contrast to many other modules in a hardware design, primitives must often be implemented in technology-dependent ways. | ||||||||||||||||||||||
For example, a clock multiplexer for a Xilinx FPGA is implemented differently than one for a specific ASIC technology. | ||||||||||||||||||||||
|
||||||||||||||||||||||
Not all primitives need to have multiple implementations. | ||||||||||||||||||||||
|
||||||||||||||||||||||
* 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 have only a FuseSoC core file in the | ||||||||||||||||||||||
`hw/ip/prim` directory. The actual implementations are in "technology | ||||||||||||||||||||||
libraries". We call these primitives "technology-dependent primitives". | ||||||||||||||||||||||
|
||||||||||||||||||||||
### Abstract primitives | ||||||||||||||||||||||
|
||||||||||||||||||||||
Abstract primitives are wrappers around technology-dependent implementations of | ||||||||||||||||||||||
primitives, with the ability to select a specific implementation if needed. | ||||||||||||||||||||||
|
||||||||||||||||||||||
In more technical terms, abstract primitives are SystemVerilog modules. The | ||||||||||||||||||||||
example below shows one. | ||||||||||||||||||||||
|
||||||||||||||||||||||
```systemverilog | ||||||||||||||||||||||
`ifndef PRIM_DEFAULT_IMPL | ||||||||||||||||||||||
`define PRIM_DEFAULT_IMPL prim_pkg::ImplGeneric | ||||||||||||||||||||||
`endif | ||||||||||||||||||||||
|
||||||||||||||||||||||
module prim_pad_wrapper | ||||||||||||||||||||||
#( | ||||||||||||||||||||||
parameter int unsigned AttrDw = 6 | ||||||||||||||||||||||
) ( | ||||||||||||||||||||||
inout wire inout_io, // bidirectional pad | ||||||||||||||||||||||
output logic in_o, // input data | ||||||||||||||||||||||
input out_i, // output data | ||||||||||||||||||||||
input oe_i, // output enable | ||||||||||||||||||||||
// additional attributes {drive strength, keeper, pull-up, pull-down, open-drain, invert} | ||||||||||||||||||||||
input [AttrDw-1:0] attr_i | ||||||||||||||||||||||
); | ||||||||||||||||||||||
parameter prim_pkg::impl_e Impl = `PRIM_DEFAULT_IMPL; | ||||||||||||||||||||||
|
||||||||||||||||||||||
if (Impl == prim_pkg::ImplGeneric) begin : gen_generic | ||||||||||||||||||||||
prim_generic_pad_wrapper u_impl_generic ( | ||||||||||||||||||||||
.* | ||||||||||||||||||||||
); | ||||||||||||||||||||||
end else if (Impl == prim_pkg::ImplXilinx) begin : gen_xilinx | ||||||||||||||||||||||
prim_xilinx_pad_wrapper u_impl_xilinx ( | ||||||||||||||||||||||
.* | ||||||||||||||||||||||
); | ||||||||||||||||||||||
end else begin : gen_failure | ||||||||||||||||||||||
// TODO: Find code that works across tools and causes a compile failure | ||||||||||||||||||||||
end | ||||||||||||||||||||||
|
||||||||||||||||||||||
endmodule | ||||||||||||||||||||||
``` | ||||||||||||||||||||||
* 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/`. | ||||||||||||||||||||||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. nit:
Suggested change
|
||||||||||||||||||||||
|
||||||||||||||||||||||
As seen from the source code snippet, abstract primitives have the following | ||||||||||||||||||||||
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. | ||||||||||||||||||||||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. nit:
Suggested change
|
||||||||||||||||||||||
It also serves as a definition of a technology-dependent primitive's interface. | ||||||||||||||||||||||
However, other technology libraries can be supersets of the generic technology library. | ||||||||||||||||||||||
|
||||||||||||||||||||||
- They have an `Impl` parameter which can be set to choose a specific | ||||||||||||||||||||||
implementation of the primitive. | ||||||||||||||||||||||
- The `Impl` parameter is set to a system-wide default determined by the | ||||||||||||||||||||||
`PRIM_DEFAULT_IMPL` define. | ||||||||||||||||||||||
- All ports and parameters of the abstract primitive are forwarded to the | ||||||||||||||||||||||
implementations. | ||||||||||||||||||||||
|
||||||||||||||||||||||
### Technology libraries | ||||||||||||||||||||||
### Virtual primitives | ||||||||||||||||||||||
|
||||||||||||||||||||||
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.* | ||||||||||||||||||||||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. nit:
Suggested change
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 👍, and I think the |
||||||||||||||||||||||
These can be thought of as similar to virtual methods in C++ or SystemVerilog. | ||||||||||||||||||||||
There was a problem hiding this comment. Choose a reason for hiding this commentThe 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
There was a problem hiding this comment. Choose a reason for hiding this commentThe 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 😉) |
||||||||||||||||||||||
A hardware block can depend on a virtual core, which can then be substituted for a *concrete* implementation by the user. | ||||||||||||||||||||||
|
||||||||||||||||||||||
At least one technology library must exist: the `generic` technology library, | ||||||||||||||||||||||
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/`. | ||||||||||||||||||||||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. nit:
Suggested change
|
||||||||||||||||||||||
Taking `hw/ip/prim_generic/prim_generic_flop_2sync.core` as an example, you'll see the following at the head of the file. | ||||||||||||||||||||||
|
||||||||||||||||||||||
In addition to the implementation in the `generic` library, primitives may be | ||||||||||||||||||||||
implemented by as many other libraries as needed. | ||||||||||||||||||||||
```yaml | ||||||||||||||||||||||
name: "lowrisc:prim_generic:flop_2sync" | ||||||||||||||||||||||
description: "Generic implementation of a flop-based synchronizer" | ||||||||||||||||||||||
virtual: | ||||||||||||||||||||||
- lowrisc:prim:flop_2sync | ||||||||||||||||||||||
``` | ||||||||||||||||||||||
|
||||||||||||||||||||||
Technology libraries are referenced by their name. | ||||||||||||||||||||||
The VLNV (Vendor Library Name Version) of the core is `lowrisc:prim_generic:flop_2sync`, but it also provides a virtual core with the VLNV of `lowrisc:prim:flop_2sync`. | ||||||||||||||||||||||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. nit:
Suggested change
|
||||||||||||||||||||||
Hardware blocks should depend on this virtual VLNV, so that the user can change implementations. | ||||||||||||||||||||||
|
||||||||||||||||||||||
### Technology library discovery | ||||||||||||||||||||||
If an implementation of a virtual core exists in an invokable core's dependency tree, it will be selected. | ||||||||||||||||||||||
You can't have multiple implementations of a virtual core in a core's dependency tree. | ||||||||||||||||||||||
*An invokable core is the core who's target is being run by FuseSoC.* | ||||||||||||||||||||||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. nit:
Suggested change
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Or "[..] core whose target is being run [..]"? There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. "whose" is technically meant to be used with people, rather than objects, but I'm certainly not going to die on that hill ;) |
||||||||||||||||||||||
|
||||||||||||||||||||||
In many cases, technology libraries contain vendor-specific code which cannot be | ||||||||||||||||||||||
shared widely or openly. Therefore, a FuseSoC looks for available technology | ||||||||||||||||||||||
libraries at build time, and makes all libraries it finds available. | ||||||||||||||||||||||
For this reason, usually an invokable core will have their chosen concrete implementation in their dependency tree. | ||||||||||||||||||||||
To reduce the hassle of pulling in a set of implementations into a dependency tree, implementations will provide `:all` core, e.g. `lowrisc:prim_generic:all`. | ||||||||||||||||||||||
The invokable core `hw/top_earlgrey/chip_earlgrey_cw310.core`, for example, depends on `lowrisc:prim_xilinx:all`. | ||||||||||||||||||||||
|
||||||||||||||||||||||
The discovery is performed based on the agreed-on naming scheme for primitives. | ||||||||||||||||||||||
[virtual cores]: https://fusesoc.readthedocs.io/en/stable/user/build_system/virtual_cores.html | ||||||||||||||||||||||
Comment on lines
+79
to
+83
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. nit: Change to "may," since invokable cores definitely don't need to specify the provider in the core files (e.g. block-level sims would best punt that to command-line args)
Suggested change
|
||||||||||||||||||||||
|
||||||||||||||||||||||
- FuseSoC scans all libraries (e.g. as specified by its `--cores-root` command | ||||||||||||||||||||||
line argument) for cores. | ||||||||||||||||||||||
- All cores with a name matching `lowrisc:prim_TECHLIBNAME:PRIMNAME` | ||||||||||||||||||||||
are considered. `TECHLIBNAME` is then added to the list of technology | ||||||||||||||||||||||
libraries. | ||||||||||||||||||||||
|
||||||||||||||||||||||
After the discovery process has completed, a script (`primgen`) creates | ||||||||||||||||||||||
- an abstract primitive (see above), and | ||||||||||||||||||||||
- an entry in the `prim_pkg` package in the form of `prim_pkg::ImplTechlibname` | ||||||||||||||||||||||
to identify the technology library by its name. | ||||||||||||||||||||||
### Mappings | ||||||||||||||||||||||
|
||||||||||||||||||||||
## User Guide | ||||||||||||||||||||||
Some invokable cores are expected to be used with multiple different implementations. | ||||||||||||||||||||||
To allow users to change primitive implementations, OpenTitan makes use of a FuseSoC feature called *[mappings][]*. | ||||||||||||||||||||||
This can be used to request a substitution of particular virtual cores with the desired implementation. | ||||||||||||||||||||||
An example of their use is in `hw/ip/prim_xilinx/prim_xilinx.core`: | ||||||||||||||||||||||
|
||||||||||||||||||||||
### Use primitives | ||||||||||||||||||||||
|
||||||||||||||||||||||
Primitives are normal SystemVerilog modules, and can be used as usual: | ||||||||||||||||||||||
* instantiate it like a normal SystemVerilog module, and | ||||||||||||||||||||||
* add a dependency in the FuseSoC core file. | ||||||||||||||||||||||
|
||||||||||||||||||||||
Technology-dependent primitives have an additional parameter called `Impl`. | ||||||||||||||||||||||
Set this parameter to use a specific implementation of the primitive for this | ||||||||||||||||||||||
specific instance. For example: | ||||||||||||||||||||||
|
||||||||||||||||||||||
```systemverilog | ||||||||||||||||||||||
prim_ram_2p #( | ||||||||||||||||||||||
.Width (TotalWidth), | ||||||||||||||||||||||
.Depth (Depth), | ||||||||||||||||||||||
// Force the use of the tsmc40lp technology library for this instance, instead | ||||||||||||||||||||||
// of using the build-time default. | ||||||||||||||||||||||
.Impl(prim_pkg::ImplTsmc40lp) | ||||||||||||||||||||||
) u_mem ( | ||||||||||||||||||||||
.clk_a_i (clk_i), | ||||||||||||||||||||||
... | ||||||||||||||||||||||
) | ||||||||||||||||||||||
```yaml | ||||||||||||||||||||||
mapping: | ||||||||||||||||||||||
"lowrisc:prim:and2" : lowrisc:prim_xilinx:and2 | ||||||||||||||||||||||
"lowrisc:prim:buf" : lowrisc:prim_xilinx:buf | ||||||||||||||||||||||
"lowrisc:prim:clock_buf" : lowrisc:prim_xilinx:clock_buf | ||||||||||||||||||||||
"lowrisc:prim:clock_div" : lowrisc:prim_generic:clock_div | ||||||||||||||||||||||
"lowrisc:prim:clock_gating" : lowrisc:prim_xilinx:clock_gating | ||||||||||||||||||||||
"lowrisc:prim:clock_inv" : lowrisc:prim_generic:clock_inv | ||||||||||||||||||||||
"lowrisc:prim:clock_mux2" : lowrisc:prim_xilinx:clock_mux2 | ||||||||||||||||||||||
# ... | ||||||||||||||||||||||
``` | ||||||||||||||||||||||
|
||||||||||||||||||||||
Notice that there aren't xilinx specific implementations for all primitives, so the generic implementation is requested. | ||||||||||||||||||||||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
Suggested change
|
||||||||||||||||||||||
|
||||||||||||||||||||||
### Set the default technology library | ||||||||||||||||||||||
Beyond primitives, mappings are also used in the top-level core files, e.g. in `hw/top_earlgrey/top_earlgrey.core`, to ask for top specific implementations. | ||||||||||||||||||||||
|
||||||||||||||||||||||
If no specific technology library is chosen for an instantiated primitive the | ||||||||||||||||||||||
default library is used. The SystemVerilog define `PRIM_DEFAULT_IMPL` can be | ||||||||||||||||||||||
used to set the default for the whole design. Set this define to one of the enum | ||||||||||||||||||||||
values in `prim_pkg.sv` in the form `prim_pkg::ImplTechlibname`. `Techlibname` | ||||||||||||||||||||||
is the capitalized name of the technology library. | ||||||||||||||||||||||
A specific use of mappings is the lints for each block, for example `hw/ip/uart/uart.core`'s lint target. | ||||||||||||||||||||||
None of it's dependencies contain concrete primitive implementations. | ||||||||||||||||||||||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. nit:
Suggested change
|
||||||||||||||||||||||
Instead mappings are used when dvsim invokes the core. | ||||||||||||||||||||||
This allows the block to be linted for multiple different primitives (and top-level constants). | ||||||||||||||||||||||
|
||||||||||||||||||||||
In the top-level FuseSoC core file the default technology library can be chosen | ||||||||||||||||||||||
like this: | ||||||||||||||||||||||
[mappings]: https://fusesoc.readthedocs.io/en/stable/user/build_system/mappings.html | ||||||||||||||||||||||
|
||||||||||||||||||||||
```yaml | ||||||||||||||||||||||
# my_toplevel.core | ||||||||||||||||||||||
|
||||||||||||||||||||||
# Declare filesets and other things (omitted) | ||||||||||||||||||||||
|
||||||||||||||||||||||
parameters: | ||||||||||||||||||||||
# Make the parameter known to FuseSoC to enable overrides from the | ||||||||||||||||||||||
# command line. If not overwritten, use the generic technology library. | ||||||||||||||||||||||
PRIM_DEFAULT_IMPL: | ||||||||||||||||||||||
datatype: str | ||||||||||||||||||||||
paramtype: vlogdefine | ||||||||||||||||||||||
description: Primitives implementation to use, e.g. "prim_pkg::ImplGeneric". | ||||||||||||||||||||||
default: prim_pkg::ImplGeneric | ||||||||||||||||||||||
|
||||||||||||||||||||||
targets: | ||||||||||||||||||||||
fpga_synthesis: | ||||||||||||||||||||||
filesets: | ||||||||||||||||||||||
- my_rtl_files | ||||||||||||||||||||||
parameters: | ||||||||||||||||||||||
# Use the xilinx technology library for this target by default. | ||||||||||||||||||||||
- PRIM_DEFAULT_IMPL=prim_pkg::ImplXilinx | ||||||||||||||||||||||
toplevel: my_toplevel | ||||||||||||||||||||||
``` | ||||||||||||||||||||||
|
||||||||||||||||||||||
## User Guide | ||||||||||||||||||||||
### Using primitives | ||||||||||||||||||||||
|
||||||||||||||||||||||
Primitives are normal SystemVerilog modules, and can be used as usual: | ||||||||||||||||||||||
1. Instantiate it like a normal SystemVerilog module. | ||||||||||||||||||||||
```systemverilog | ||||||||||||||||||||||
prim_fifo_sync #( | ||||||||||||||||||||||
.Width (8), | ||||||||||||||||||||||
.Pass (1'b0), | ||||||||||||||||||||||
.Depth (TxFifoDepth) | ||||||||||||||||||||||
) u_uart_txfifo ( | ||||||||||||||||||||||
.clk_i, | ||||||||||||||||||||||
// .. | ||||||||||||||||||||||
.err_o () | ||||||||||||||||||||||
) | ||||||||||||||||||||||
``` | ||||||||||||||||||||||
2. Add it as a dependency in the FuseSoC core file. | ||||||||||||||||||||||
```yaml | ||||||||||||||||||||||
name: "lowrisc:ip:uart:0.1" | ||||||||||||||||||||||
description: "uart" | ||||||||||||||||||||||
filesets: | ||||||||||||||||||||||
files_rtl: | ||||||||||||||||||||||
depend: | ||||||||||||||||||||||
- lowrisc:virtual_constants:top_pkg | ||||||||||||||||||||||
- lowrisc:prim:prim_fifo_sync | ||||||||||||||||||||||
``` | ||||||||||||||||||||||
|
||||||||||||||||||||||
|
||||||||||||||||||||||
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.** | ||||||||||||||||||||||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. nit: Best to provide a reason alongside recommendations.
Suggested change
|
||||||||||||||||||||||
|
||||||||||||||||||||||
|
||||||||||||||||||||||
### Create a technology library | ||||||||||||||||||||||
|
||||||||||||||||||||||
To create a technology library follow these steps: | ||||||||||||||||||||||
|
||||||||||||||||||||||
- Choose a name for the new technology library. Names are all lower-case. | ||||||||||||||||||||||
To ease sharing of technology libraries it is encouraged to pick a very | ||||||||||||||||||||||
specific name, e.g. `tsmc40lp`, and not `asic`. | ||||||||||||||||||||||
- Copy the `prim_generic` folder into an arbitrary location (can be outside | ||||||||||||||||||||||
of this repository). Name the folder `prim_YOURLIBRARYNAME`. | ||||||||||||||||||||||
- Replace the word `generic` everywhere with the name of your technology | ||||||||||||||||||||||
library. This includes | ||||||||||||||||||||||
- file and directory names (e.g. `prim_generic_ram1p.sv` becomes | ||||||||||||||||||||||
`prim_tsmc40lp_ram1p.sv`), | ||||||||||||||||||||||
- module names (e.g. `prim_generic_ram1p` becomes `prim_tsmc40lp_ram1p`), and | ||||||||||||||||||||||
- all other references (grep for it!). | ||||||||||||||||||||||
- Implement all primitives. Replace the module body of the generic | ||||||||||||||||||||||
implementation with a technology-specific implementation as needed. Do *not* | ||||||||||||||||||||||
modify the list of ports or parameters in any way! | ||||||||||||||||||||||
|
||||||||||||||||||||||
## Implementation details | ||||||||||||||||||||||
|
||||||||||||||||||||||
Technology-dependent primitives are implemented as a FuseSoC generator. The | ||||||||||||||||||||||
core of the primitive (e.g. `lowrisc:prim:rom` in `prim/prim_rom.core`) calls | ||||||||||||||||||||||
a FuseSoC generator. This generator is the script `util/primgen.py`. As input, | ||||||||||||||||||||||
the script receives a list of all cores found by FuseSoC anywhere in its search | ||||||||||||||||||||||
path. The script then looks through the cores FuseSoC discovered and extracts | ||||||||||||||||||||||
a list of technology libraries out of it. It then goes on to create the | ||||||||||||||||||||||
abstract primitive (copying over the list of parameters and ports from the | ||||||||||||||||||||||
generic implementation), and an associated core file, which depends on all | ||||||||||||||||||||||
technology-dependent libraries that were found. | ||||||||||||||||||||||
1. Choose a name for the new technology library. | ||||||||||||||||||||||
Names are all lower-case. | ||||||||||||||||||||||
To ease sharing of technology libraries it is encouraged to pick a very specific name, rather than a generic name like `asic`. | ||||||||||||||||||||||
`mytech` will be used as a placeholder name in the examples. | ||||||||||||||||||||||
2. Create a directory in `hw/ip` with the prefix `prim_` followed by the name of your technology library. | ||||||||||||||||||||||
3. Copy `hw/ip/prim_generic/prim_generic.core` into the new directory renaming it to match your primitive library, e.g. `hw/ip/prim_mytech/prim_mytech.core` | ||||||||||||||||||||||
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`. | ||||||||||||||||||||||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
Suggested change
Unless you've aliased |
||||||||||||||||||||||
2. Make your changes to the implementation without modifying the module ports or removing parameters. | ||||||||||||||||||||||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
Suggested change
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. There was a problem hiding this comment. Choose a reason for hiding this commentThe 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. |
||||||||||||||||||||||
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`. | ||||||||||||||||||||||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
Suggested change
|
||||||||||||||||||||||
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. | ||||||||||||||||||||||
There was a problem hiding this comment. Choose a reason for hiding this commentThe 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 |
||||||||||||||||||||||
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`. | ||||||||||||||||||||||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. nit:
Suggested change
|
||||||||||||||||||||||
This is useful in cases where technology libraries contain vendor-specific code which cannot be shared widely or openly. | ||||||||||||||||||||||
|
||||||||||||||||||||||
|
||||||||||||||||||||||
### Selecting a technology library | ||||||||||||||||||||||
|
||||||||||||||||||||||
You can select a technology library one of two ways. | ||||||||||||||||||||||
There was a problem hiding this comment. Choose a reason for hiding this commentThe 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. | ||||||||||||||||||||||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. nit:
Suggested change
|
||||||||||||||||||||||
`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. | ||||||||||||||||||||||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. nit:
Suggested change
|
||||||||||||||||||||||
|
||||||||||||||||||||||
If you are using an invokable core which is generic across different technology libraries, then you should use mappings to select the technology library you'd like to use. | ||||||||||||||||||||||
A default technology library sometimes exists for these invokable cores. | ||||||||||||||||||||||
The default technology library needs to be disabled with a flag. | ||||||||||||||||||||||
`hw/top_earlgrey/chip_earlgrey_asic.core` is an example of one of these invokable cores. | ||||||||||||||||||||||
You provide the `fileset_partner` flag to disable the default implementation as well as your mapping. | ||||||||||||||||||||||
|
||||||||||||||||||||||
```sh | ||||||||||||||||||||||
fusesoc --cores-root=$OT_REPO run \ | ||||||||||||||||||||||
--flag fileset_partner \ | ||||||||||||||||||||||
--mapping partner:prim_mytech:all | ||||||||||||||||||||||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
Suggested change
|
||||||||||||||||||||||
lowrisc:systems:chip_earlgrey_asic | ||||||||||||||||||||||
``` |
Uh oh!
There was an error while loading. Please reload this page.