27

✨[Zxcfu ISA ext.] add option to implement custom RISC-V instructions by stnoltin...

 2 years ago
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.

Copy link

Owner

stnolting commented 4 days ago

edited

With this PR the NEORV32 now provides an option to add custom RISC-V instructions. rocket

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-extension
  • x = the second letter behind the Z defines the "parent-extension" where this sub-extension belongs to: in this case it belongs to the X "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.

About Joyk


Aggregate valuable and interesting links.
Joyk means Joy of geeK