Update code from upstream repository https://github.com/lowRISC/opentitan to revision 7e131447da6d5f3044666a17974e15df44f0328b Updates to Ibex code to match this import: * Include str_utils in the imported code. * List new source files in dv/uvm/core_ibex/ibex_dv.f * Update patches to resolve merge conflicts. * Update tb_cs_registers.cc and ibex_riscv_compliance.cc to match the new return code of simctrl.Exec(). Imported updates: * Do not require pyyaml >= 5.1 (Philipp Wagner) * [prim_edn_req] Forward fips signal to consumer (Pirmin Vogel) * [prim_edn_req] Use prim_sync_reqack_data primitive (Pirmin Vogel) * [prim_edn_req] De-assert EDN request if packer FIFO has data available (Pirmin Vogel) * [cleanup] Mass replace tabs with spaces (Srikrishna Iyer) * [lc_ctrl] Add script to generate the LC state based on the ECC poly (Michael Schaffner) * [dvsim] Use list for rsync command (Eunchan Kim) * [verilator] Only control the reset line when necessary (Rupert Swarbrick) * [dv/csr_utils] Add debug msg for UVM_NOT_OK err (Cindy Chen) * [dvsim] Add exclude hidden files when needed (Eunchan Kim) * [prim_sync_reqack] Add variant with associated data and optional data reg (Pirmin Vogel) * [DV, Xcelium] Fix for lowRISC/opentitan#4690 (Srikrishna Iyer) * [dvsim] Remote copy update (Srikrishna Iyer) * [prim_edn_req] Add EDN sync and packer gadget primitive (Michael Schaffner) * [prim] Add hamming code as ECC option (Timothy Chen) * [DV] Cleanup lint warnings with Verible lint (¨Srikrishna) * [prim_ram] Rearrange parity bit packing and fix wrong wmask settings (Michael Schaffner) * [lc_sync/lc_sender] Absorb flops within lc_sender (Michael Schaffner) * [prim_otp_pkg] Move prim interface constants into separate package (Michael Schaffner) * [sram_ctrl] Pull scr macro out of sram_ctrl (Michael Schaffner) * [top] Move alert handler to periphs and attach escalation clock to ibex (Michael Schaffner) * [prim_esc_rxtx/rv_core_ibex] Add default values and NMI synchronization (Michael Schaffner) * [dvsim] Fix regression publish result link with --remote switch (Cindy Chen) * [vendor/ibex] Remove duplicate check tool requirements files (Michael Schaffner) * [prim_ram_1p_scr] Fix sequencing bug in scrambling logic (Michael Schaffner) * [prim_ram*_adv] Qualify error output signals with rvalid (Michael Schaffner) * [dvsim] Fix purge not delete remote repo_top (Cindy Chen) * [lc/otp/alerts] Place size-only buffers on all multibit signals (Michael Schaffner) * [prim_buf] Add generic and Xilinx buffer primitive (Michael Schaffner) * [prim] Packer to add byte hint assertion (Eunchan Kim) * [dvsim] Logic to copy repo to scratch area (Srikrishna Iyer) * [dv/lc_ctrl] enable lc_ctrl alert_test (Cindy Chen) * [prim] documentation update for flash (Timothy Chen) * [flash_ctrl] Add additional interface support (Timothy Chen) * [dvsim] Fix publish report path (Weicai Yang) * [top_earlgrey] Instantiate LC controller in toplevel (Michael Schaffner) * [doc] Fix checklist items in V1 (Michael Schaffner) * [dv/csr_excl] Fix VCS warning (Cindy Chen) * [dv/doc] cleaned up checkist alignment (Rasmus Madsen) * [doc/dv] cleanup (Rasmus Madsen) * [dv/doc] updated dv_plan links to new location (Rasmus Madsen) * [dv/doc] changed testplan to dv_plan in markdown files (Rasmus Madsen) * [dv/doc] changed dv plan to dv doc (Rasmus Madsen) * Remove redundant ascentlint options (Olof Kindgren) * Add ascentlint default options for all cores depending on lint:common (Olof Kindgren) * [flash] documentation update (Timothy Chen) * [flash / top] Add info_sel to flash interface (Timothy Chen) * [otp] lci interface assertion related fix (Cindy Chen) * [dv/uvmdvgen] Add switch to auto-gen edn (Cindy Chen) * [util] Rejig how we load hjson configurations for dvsim.py (Rupert Swarbrick) * added changes required by sriyerg (Dawid Zimonczyk) * update riviera.hjson (Dawid Zimonczyk) * [flash_ctrl] Add high endurance region attribute (Timothy Chen) * Change VerilatorSimCtrl::Exec to handle --help properly (Rupert Swarbrick) * Simplify handling of exit_app in VerilatorSimCtrl::ParseCommandArgs (Rupert Swarbrick) * [sram_ctrl] Rtl lint fix (Michael Schaffner) * [keymgr] Add edn support (Timothy Chen) * [dv] Make width conversion explicit in dv_base_env_cfg::initialize (Rupert Swarbrick) * [dvsim] Allow dvsim.py to be run under Make (Rupert Swarbrick) * [dvsim[ rename revision_string to revision (Srikrishna Iyer) * [dvsim] Update log messages (Srikrishna Iyer) * [dvsim] fix for full verbosity (Srikrishna Iyer) * [dv] Fix Questa warning and remove unused var (Weicai Yang) * [dvsim] Add alias for --run-only (Weicai Yang) * [keymgr] Hook-up random compile time constants (Timothy Chen) * [dvsim] Add support for UVM_FULL over cmd line (Srikrishna Iyer) * [dv common] Enable DV macros in non-UVM components (Srikrishna Iyer) * [DVsim] Add support for Verilator (Srikrishna Iyer) * [DVSim] Fix how sw_images is treated (Srikrishna Iyer) * [DV common] Fixes in sim.mk for Verilator (Srikrishna Iyer) * [DV Common] Split DV test status reporting logic (Srikrishna Iyer) * [prim_arbiter_ppc] Fix lint error (Philipp Wagner) * [DV common] Factor `sim_tops` out of build_opts (Srikrishna Iyer) * [dvsim] run yapf to fix style (Weicai Yang) * [dv/common] VCS UNR flow (Weicai Yang) * [dv] Add get_max_offset function in dv_base_reg_block (Weicai Yang) * [otp_ctrl] Fix warnings from VCS (Cindy Chen) * [lint] Change unused_ waiver (Eunchan Kim) * [dv/alert_test] Add alert_test IP level automation test (Cindy Chen) * [DV] Update the was SW is built for DV (Srikrishna Iyer) * [dvsim] Replace `sw_test` with `sw_images` (Srikrishna Iyer) * [chip dv] Move sw build directory (Srikrishna Iyer) * [dv common] Update dv_utils to use str_utils_pkg (Srikrishna Iyer) * [DVSim] Method to add pre/post build/run steps (Srikrishna Iyer) Signed-off-by: Philipp Wagner <phw@lowrisc.org> |
||
---|---|---|
.. | ||
doc | ||
dv | ||
fpv | ||
lint | ||
pre_dv/prim_sync_reqack | ||
rtl | ||
util | ||
prim.core | ||
prim_assert.core | ||
prim_buf.core | ||
prim_clock_buf.core | ||
prim_clock_div.core | ||
prim_clock_gating.core | ||
prim_clock_inv.core | ||
prim_clock_mux2.core | ||
prim_diff_decode.core | ||
prim_dom_and_2share.core | ||
prim_edn_req.core | ||
prim_flash.core | ||
prim_flop.core | ||
prim_flop_2sync.core | ||
prim_gf_mult.core | ||
prim_lc_sender.core | ||
prim_lc_sync.core | ||
prim_lfsr.core | ||
prim_multibit_sync.core | ||
prim_otp.core | ||
prim_otp_pkg.core | ||
prim_pad_wrapper.core | ||
prim_pkg.core | ||
prim_ram_1p.core | ||
prim_ram_1p_adv.core | ||
prim_ram_1p_scr.core | ||
prim_ram_2p.core | ||
prim_ram_2p_adv.core | ||
prim_ram_2p_async_adv.core | ||
prim_rom.core | ||
prim_rom_adv.core | ||
prim_secded.core | ||
prim_usb_diff_rx.core | ||
prim_util.core | ||
prim_util_memload.core | ||
primgen.core | ||
README.md |
lowRISC Hardware Primitives
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.
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.
`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
As seen from the source code snippet, abstract primitives have the following properties:
- 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 thePRIM_DEFAULT_IMPL
define. - All ports and parameters of the abstract primitive are forwarded to the implementations.
Technology libraries
Technology libraries collect implementations of primitives.
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.
In addition to the implementation in the generic
library, primitives may be
implemented by as many other libraries as needed.
Technology libraries are referenced by their name.
Technology library discovery
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.
The discovery is performed based on the agreed-on naming scheme for primitives.
- 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 ofprim_pkg::ImplTechlibname
to identify the technology library by its name.
User Guide
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:
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),
...
)
Set the default technology library
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.
In the top-level FuseSoC core file the default technology library can be chosen like this:
# 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
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 notasic
. - Copy the
prim_generic
folder into an arbitrary location (can be outside of this repository). Name the folderprim_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
becomesprim_tsmc40lp_ram1p.sv
), - module names (e.g.
prim_generic_ram1p
becomesprim_tsmc40lp_ram1p
), and - all other references (grep for it!).
- file and directory names (e.g.
- 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.