<<<
:sectnums:
=== Custom Functions Unit (CFU)

The Custom Functions Unit (CFU) is the central part of the NEORV32-specific <<_zxcfu_isa_extension>> and
represents the actual hardware module that can be used to implement **custom RISC-V instructions**.

The CFU is intended for operations that are inefficient in terms of performance, latency, energy consumption or
program memory requirements when implemented entirely in software. Some potential application fields and exemplary
use-cases might include:

* **AI:** sub-word / vertical vector/SIMD operations like processing all four sub-bytes of a 32-bit data word individually
* **Cryptographic:** bit substitution and permutation
* **Communication:** data conversions like binary to gray-code
* **Arithmetic:** BCD (binary-coded decimal) operations; multiply-add operations; shift-and-add algorithms like CORDIC or BKM
* **Image processing:** look-up-tables for color space transformations
* implementing instructions from **other RISC-V ISA extensions** that are not yet supported by NEORV32

The NEORV32 CFU supports two different instruction formats (R3-type and R4-type; see <<_cfu_instruction_formats>>) and also
allows to implement up to 4 CFU-internal custom control and status registers (see <<_cfu_control_and_status_registers_cfu_csrs>>).

.CFU Complexity
[NOTE]
The CFU is not intended for complex and **CPU-independent** functional units that implement complete accelerators
(like block-based AES encryption). These kind of accelerators should be implemented as memory-mapped co-processor via the
<<_custom_functions_subsystem_cfs>> to allow CPU-independent operation. A comparative survey of all NEORV32-specific
hardware extension/customization options is provided in the user guide section
https://stnolting.github.io/neorv32/ug/#_adding_custom_hardware_modules[Adding Custom Hardware Modules].

.Default CFU Hardware Example
[TIP]
The default CFU module (`rtl/core/neorv32_cpu_cp_cfu.vhd`) implements the _Extended Tiny Encryption Algorithm (XTEA)_
as "real world" application example.


:sectnums:
==== CFU Instruction Formats

The custom instructions executed by the CFU utilize a specific opcode space in the `rv32` 32-bit instruction
encoding space that has been explicitly reserved for user-defined extensions by the RISC-V specifications ("Guaranteed
Non-Standard Encoding Space"). The NEORV32 CFU uses the `custom-0` and `custom-1` opcodes to identify the instruction
implemented by the CFU and to differentiate between the predefined instruction formats.

The NEORV32 CFU utilizes these two opcodes to support user-defined **R3-type** instructions (2 source registers,
1 destination register) and **R4-type** instructions (3 source registers, 1 destination register). Both instruction
formats are compliant to the RISC-V specification.

* `custom-0`: `0001011` RISC-V standard, used for NEORV32 <<_cfu_r3_type_instructions>> (3x register addresses)
* `custom-1`: `0101011` RISC-V standard, used for NEORV32 <<_cfu_r4_type_instructions>> (4x register addresses)

[TIP]
The provided instructions formats are _predefined_ to allow an easy integration framework.
However, system designers are free to ignore these and use their own instruction types and formats.


:sectnums:
===== CFU R3-Type Instructions

The R3-type CFU instructions operate on two source registers `rs1` and `rs2` and return the processing result to
the destination register `rd`. The actual operation can be defined by using the `funct7` and `funct3` bit fields.
These immediates can also be used to pass additional data to the CFU like offsets, look-up-tables addresses or
shift-amounts. However, the actual functionality is entirely user-defined. Note that all immediate values are
always compile-time-static.

Example operation: `rd <= rs1 xnor rs2` (bit-wise logical XNOR)

.CFU R3-type instruction format
image::cfu_r3type_instruction.png[align=left]

* `funct7`: 7-bit immediate (immediate data or function select)
* `rs2`: address of second source register (providing 32-bit source data)
* `rs1`: address of first source register (providing 32-bit source data)
* `funct3`: 3-bit immediate (immediate data or function select)
* `rd`: address of destination register (32-bit processing result)
* `opcode`: `0001011` (RISC-V `custom-0` opcode)

.Instruction encoding space
[NOTE]
By using the `funct7` and `funct3` bit fields entirely for selecting the actual operation a total of 1024 custom
R3-type instructions can be implemented (7-bit + 3-bit = 10 bit -> 1024 different values).


:sectnums:
===== CFU R4-Type Instructions

The R4-type CFU instructions operate on three source registers `rs1`, `rs2` and `rs2` and return the processing
result to the destination register `rd`. The actual operation can be defined by using the `funct3` bit field.
Alternatively, this immediate can also be used to pass additional data to the CFU like offsets, look-up-tables
addresses or shift-amounts. However, the actual functionality is entirely user-defined. Note that all immediate
values are always compile-time-static.

Example operation: `rd <= (rs1 * rs2 + rs3)[31:0]` (multiply-and-accumulate; "MAC")

.CFU R4-type instruction format
image::cfu_r4type_instruction.png[align=left]

* `rs3`: address of third source register (providing 32-bit source data)
* `rs2`: address of second source register (providing 32-bit source data)
* `rs1`: address of first source register (providing 32-bit source data)
* `funct3`: 3-bit immediate (immediate data or function select)
* `rd`: address of destination register (32-bit processing result)
* `opcode`: `0101011` (RISC-V `custom-1` opcode)
* ⚠️ bits [26:25] of the R4-type instruction word are unused. However, these bits are ignored
by CPU's instruction decoder and can be retrieved via the CFU's `funct7_i(6 downto 5)` signal.

.Instruction encoding space
[NOTE]
By using the `funct3` bit field entirely for selecting the actual operation a total of 8 custom R4-type
instructions can be implemented (3-bit -> 8 different values).

.Re-purposing R4-type instructions as additional R3-type instructions
[TIP]
Advanced user can use the custom-1 opcode to implement additional R3-type instructions instead of the
predefined r4-type instructions.


:sectnums:
==== Using Custom Instructions in Software

The custom instructions provided by the CFU can be used in plain C code by using **intrinsics**. Intrinsics
behave like "normal" C functions but under the hood they are a set of macros that hide the complexity of inline
assembly, which is used to construct the custom 32-bit instruction words. Using intrinsics removes the need to
modify the compiler, built-in libraries or the assembler when using custom instructions. Each intrinsic will be
compiled into a single 32-bit instruction word without any overhead providing maximum code efficiency.

The NEORV32 software framework provides two pre-defined prototypes for custom instructions, which are defined in
`sw/lib/include/neorv32_cpu_cfu.h`:

.CFU instruction prototypes
[source,c]
----
uint32_t neorv32_cfu_r3_instr(funct7, funct3, rs1, rs2); // R3-type instructions
uint32_t neorv32_cfu_r4_instr(funct3, rs1, rs2, rs3);    // R4-type instructions
----

The intrinsic functions always return a 32-bit value of type `uint32_t` (the processing result), which can be
discarded if not needed. Each intrinsic function requires several arguments depending on the instruction type/format:

* `funct7` - 7-bit immediate (R3-type)
* `funct3` - 3-bit immediate (R3-type, R4-type)
* `rs1` - source operand 1, 32-bit (R3-type, R4-type)
* `rs2` - source operand 2, 32-bit (R3-type, R4-type)
* `rs3` - source operand 3, 32-bit (R4-type)

The `funct3` and `funct7` bit-fields are used to pass 3-bit or 7-bit literals to the CFU. The `rs1`, `rs2` and
`rs3` arguments pass the actual data to the CFU via register addresses. These register arguments can be populated
with variables or literals; the compiler will add the required code to move the data into a register before
passing it to the CFU. The following examples shows how to pass arguments:

.CFU instruction usage example
[source,c]
----
uint32_t tmp = some_function();
...
uint32_t res = neorv32_cfu_r3_instr(0b0000000, 0b101, tmp, 123);
uint32_t foo = neorv32_cfu_r4_instr(0b011, tmp, res, (uint32_t)some_array[i]);
neorv32_cfu_r3_instr(0b0100100, 0b001, tmp, foo); // discard result
----

.CFU Example Program
[TIP]
There is an example program for the CFU, which shows how to use the _default_ CFU hardware module.
This example program is located in `sw/example/demo_cfu`.


:sectnums:
==== CFU Control and Status Registers (CFU-CSRs)

The CPU provides up to four control and status registers (<<_cfureg, `cfureg*`>>) to be used within the CFU.
These CSRs are mapped to the "custom user-mode read/write" CSR address space, which is explicitly reserved for
platform-specific application by the RISC-V spec. For example, these CSRs can be used to pass additional operands
to the CFU, to obtain additional results, to check processing status or to configure operation modes.

.CFU CSR Access Example
[source,c]
----
neorv32_cpu_csr_write(CSR_CFUREG0, 0xabcdabcd); // write data to CFU CSR 0
uint32_t tmp = neorv32_cpu_csr_read(CSR_CFUREG3); // read data from CFU CSR 3
----

.Additional CFU-internal CSRs
[TIP]
If more than four CFU-internal CSRs are required the designer can implement an "indirect access mechanism" based
on just two of the default CSRs: one CSR is used to configure the index while the other is used as alias to exchange
data with the indexed CFU-internal CSR - this concept is similar to the RISC-V Indirect CSR Access Extension
Specification (`Smcsrind`).

.Security Considerations
[NOTE]
The CFU CSRs are mapped to the user-mode CSR space so software running at _any privilege level_ can access these
CSRs.


:sectnums:
==== Custom Instructions Hardware

The actual functionality of the CFU's custom instructions is defined by the user-defined logic inside the CFU
hardware module (`rtl/core/neorv32_cpu_cp_cfu.vhd`). This file is highly commented to explain the interface and
to illustrate hardware design considerations.

CFU operations can be entirely combinatorial (like bit-reversal) so the result is available at the end of the
current clock cycle. However, operations can also take several clock cycles to complete (like multiplications)
and may also include internal states and memories.

.CFU Hardware Resource Requirements
[NOTE]
Enabling the CFU and actually implementing R4-type instructions (or more precisely, using the third register
source `rs3`) will add an additional read port to the core's register file increasing resource requirements
of the register file by 50%.

.CFU Execution Time
[NOTE]
The CFU has to complete computation within a **bound time window** (default = 512 clock cycles). Otherwise,
the CFU operation is terminated by the CPU execution logic and an illegal instruction exception is raised. See section
<<_cpu_arithmetic_logic_unit>> for more information.

.CFU Exception
[NOTE]
The CFU can intentionally raise an illegal instruction exception by not asserting the `done` at all causing an
execution timeout. For example this can be used to signal invalid configurations/operations to the runtime
environment. See the documentation in the CFU's VHDL source file for more information.
