![](/style/images/good.png)
![](/style/images/bad.png)
✨[Zxcfu ISA ext.] add option to implement custom RISC-V instructions by stnoltin...
source link: https://github.com/stnolting/neorv32/pull/264
Go to the source link to view the article. You can view the picture content, updated content and better typesetting reading experience. If the link is broken, please click the button below to view the snapshot at that time.
With this PR the NEORV32 now provides an option to add custom RISC-V instructions.
This PR adds a Custom Functions Unit (CFU) wrapped in the Zxcfu
ISA extension, which is a NEORV32-specific custom ISA extension. The extension's name follows the RISC-V naming scheme:
Z
= this is a sub-extensionx
= the second letter behind the Z defines the "parent-extension" where this sub-extension belongs to: in this case it belongs to theX
"custom extensions" extension (platform-specific extension that is not defined by the RISC-V spec.)cfu
= name of the extension (Custom Functions Unit)
The CFU is implemented as a new hardware module (rtl/core/neorv32_cpu_cp_cfu.vhd
) that is integrated right into the CPU's ALU. Thus, the CFU has direct access to the core's register file, which provides minimal data transfer latency. A special OPCODE, which has been officially reserved for custom extensions by the RISC-V spec, is used to build custom instructions. The custom instructions supported by the CFU use the R2-type format that provides two source registers, one destinations register and a 10-bit immediate (split into two bit-fields:
The funct7
and funct3
bit-fields can be used to pass immediates to the CFU for certain computations (for example offsets, addresses, shift-amounts, ...) or they can be used to select the actual custom instruction to be executed (allowing up to 1024 different instructions).
Software can utilize the custom instruction by using the provides intrinsics (defined in sw/lib/include/neorv32_cpu_cfu.h
. These pre-defined functions implicitly set the funct3
bit field. Each intrinsic can be treated as "normal C function" (see #263). A simple demo program using the default CFU hardware is available in sw/example/demo_cfu
.
// custom instruction prototypes neorv32_cfu_cmd0(funct7, rs1, rs2); // funct3 = 000 neorv32_cfu_cmd1(funct7, rs1, rs2); // funct3 = 001 neorv32_cfu_cmd2(funct7, rs1, rs2); // funct3 = 010 neorv32_cfu_cmd3(funct7, rs1, rs2); // funct3 = 011 neorv32_cfu_cmd4(funct7, rs1, rs2); // funct3 = 100 neorv32_cfu_cmd5(funct7, rs1, rs2); // funct3 = 101 neorv32_cfu_cmd6(funct7, rs1, rs2); // funct3 = 110 neorv32_cfu_cmd7(funct7, rs1, rs2); // funct3 = 111
This new feature was highly inspired by @google's CFU-Playground - thanks again to @umarcor for showing me that framework. With some logic plumbing it should be possible to install the CFUs from the CFU-Playground into the NEORV32.
CFU vs. CFS
There are two processor-internal options for custom hardware now: the Custom Functions Subsystem (CFS) and the Custom Functions Unit (CFU).
- Custom Functions Subsystem (CFS): The CFS is a memory-mapped peripheral that is accessed using load/store instructions. It is intended for complex accelerators that - once triggered - perform some "long" processing in a CPU-independent manner (like a complete AES encryption). The CFS also provides the option to implement custom interfaces as it has direct access to special top entity signals.
- Custom Functions Unit (CFU): The CFU is located right inside the CPU's pipeline. It is intended for custom instructions that implement certain functionality, which is not supported by the official (and supported) RISC-V ISA extensions. These instructions should be rather simple data transformations (like bit-reversal, summing elements in a vector, elementary AES operations, ...) rather than implementing a complete algorithm (even if this is also supported) since the CFU instructions are absolutely CPU-dependent and will stall the core until completed.
Recommend
About Joyk
Aggregate valuable and interesting links.
Joyk means Joy of geeK