Merge pull request #190 from stnolting/bit_manipulation_zba

[B ISA Extension] Rework and addition of Zba subset
This commit is contained in:
Stephan Nolting 2021-10-29 18:07:04 +02:00 committed by GitHub
commit 9d5fe55b63
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
25 changed files with 416 additions and 196 deletions

View file

@ -26,6 +26,7 @@ defined by the `hw_version_c` constant in the main VHDL package file [`rtl/core/
| Date (*dd.mm.yyyy*) | Version | Comment |
|:----------:|:-------:|:--------|
| 28.10.2021 | 1.6.2.11 | :sparkles: added `Zba` bit-manipulation sub-extension; :warning: removed configuration option for `B` sub-extensions: removed `CPU_EXTENSION_RISCV_Zbb` generic and according SYSINFO flag, added new `CPU_EXTENSION_RISCV_B` generic (to implement bit-manipulation `B` ISA extension with _all_ currently supported subsets), see [PR #190](https://github.com/stnolting/neorv32/pull/190) |
| 27.10.2021 | 1.6.2.10 | :bug: CPU control unit: fixed _imprecise_ illegal instruction exceptions - `MEPC` and `MTAVL` did not reflect the correct exception-causing data for illegal ALU-class (non-multi-cycle like `SUB`) operations; optimized critical path of exception logic (illegal compressed instruction detection) |
| 27.10.2021 | 1.6.2.9 | CPU control unit: minor logic optimization - `fence.i` instruction needs 1 cycle less to execute, reduced HW footprint of control engine, shortened CPU's critical path (PC update logic) |
| 26.10.2021 | 1.6.2.8 | :bug: bootloader: fixed bug in stack pointer initialization (introduced in version `1.6.2.7`); minor SPI unit VHDL code clean-up |

View file

@ -192,11 +192,11 @@ documentation section). Note that the `X` extension is always enabled.
[[`I`](https://stnolting.github.io/neorv32/#_i_base_integer_isa)/
[`E`](https://stnolting.github.io/neorv32/#_e_embedded_cpu)]
[[`A`](https://stnolting.github.io/neorv32/#_a_atomic_memory_access)]
[[`B`](https://stnolting.github.io/neorv32/#_b_bit_manipulation_operations)]
[[`C`](https://stnolting.github.io/neorv32/#_c_compressed_instructions)]
[[`M`](https://stnolting.github.io/neorv32/#_m_integer_multiplication_and_division)]
[[`U`](https://stnolting.github.io/neorv32/#_u_less_privileged_user_mode)]
[[`X`](https://stnolting.github.io/neorv32/#_x_neorv32_specific_custom_extensions)]
[[`Zbb`](https://stnolting.github.io/neorv32/#_zbb_basic_bit_manipulation_operations)]
[[`Zfinx`](https://stnolting.github.io/neorv32/#_zfinx_single_precision_floating_point_operations)]
[[`Zicsr`](https://stnolting.github.io/neorv32/#_zicsr_control_and_status_register_access_privileged_architecture)]
[[`Zifencei`](https://stnolting.github.io/neorv32/#_zifencei_instruction_stream_synchronization)]
@ -205,7 +205,7 @@ documentation section). Note that the `X` extension is always enabled.
[[`HPM`](https://stnolting.github.io/neorv32/#_hpm_hardware_performance_monitors)]
[[`DEBUG`](https://stnolting.github.io/neorv32/#_cpu_debug_mode)]**
:warning: The `Zbb`, `Zfinx` and `Zmmul` RISC-V extensions are frozen but not officially ratified yet. Hence, there is no
:warning: The `B`, `Zfinx` and `Zmmul` RISC-V extensions are frozen but not officially ratified yet. Hence, there is no
upstream gcc support. To circumvent this, the NEORV32 software framework provides _intrinsic_ libraries for these extensions.
[[back to top](#The-NEORV32-RISC-V-Processor)]

View file

@ -8,12 +8,12 @@ image::riscv_logo.png[width=350,align=center]
* 32-bit multi-cycle in-order `rv32` RISC-V CPU
* Optional RISC-V extensions:
** `A` - atomic memory access operations
** `B` - bit-manipulation instructions
** `C` - 16-bit compressed instructions
** `I` - integer base ISA (always enabled)
** `E` - embedded CPU version (reduced register file size)
** `M` - integer multiplication and division hardware
** `U` - less-privileged _user_ mode
** `Zbb` - basic bit-manipulation operations
** `Zfinx` - single-precision floating-point unit
** `Zicsr` - control and status register access (privileged architecture)
** `Zifencei` - instruction stream synchronization
@ -268,6 +268,11 @@ only supports the modes _OFF_ and _NAPOT_ yet and a minimal granularity of 8 byt
The `A` CPU extension only implements the `lr.w` and `sc.w` instructions yet.
However, these instructions are sufficient to emulate all further atomic memory operations.
.Bit-manipulation operations
[IMPORTANT]
The NEORV32 `B` extension only implements the _basic bit-manipulation instructions_ (`Zbb`) subset
and the _address generation instructions_ (`Zba`) subset yet.
.Instruction Misalignment
[NOTE]
This is not a real RISC-V incompatibility, but something that might not be clear when studying the RISC-V privileged
@ -276,7 +281,6 @@ is raised if bit 1 of the access address is set (i.e. not on 32-bit boundary). I
there will be no misaligned instruction exceptions _at all_.
In both cases bit 0 of the program counter and all related registers is hardwired to zero.
<<<
// ####################################################################################################################
:sectnums:
@ -417,6 +421,42 @@ The atomic instructions have special requirements for memory system / bus interc
information can be found in sections <<_bus_interface>> and <<_processor_external_memory_interface_wishbone_axi4_lite>>, respectively.
==== **`B`** - Bit-Manipulation Operations
The `B` ISA extension adds instructions for bit-manipulation operations. This extension is enabled if the
`CPU_EXTENSION_RISCV_B` configuration generic is _true_.
The official RISC-V specifications can be found here: https://github.com/riscv/riscv-bitmanip
[IMPORTANT]
The NEORV32 `B` extension only implements the _basic bit-manipulation instructions_ (`Zbb`) subset
and the _address generation instructions_ (`Zba`) subset yet.
The `Zbb` sub-extension adds the following instruction:
* `andn`, `orn`, `xnor`
* `clz`, `ctz`, `cpop`
* `max`, `maxu`, `min`, `minu`
* `sext.b`, `sext.h`, `zext.h`
* `rol`, `ror`, `rori`
* `orc.b`, `rev8`
The `Zba` sub-extension adds the following instruction:
* `sh1add`, `sh2add`, `sh3add`
[TIP]
By default, the bit-manipulation unit uses an _iterative_ approach to compute shift-related operations
like `clz` and `rol`. To increase performance (at the cost of additional hardware resources) the
<<_fast_shift_en>> generic can be enabled to implement full-parallel logic (like barrel shifters) for all
shift-related `B` instructions.
[WARNING]
The `B` extension is frozen but not officially ratified yet. There is no
software support for this extension in the upstream GCC RISC-V port yet. However, an
intrinsic library is provided to utilize the provided `B` extension features from C-language
code (see `sw/example/bitmanip_test`).
==== **`C`** - Compressed Instructions
The _compressed_ ISA extension provides 16-bit encodings of commonly used instructions to reduce code space size.
@ -566,34 +606,6 @@ intrinsic library is provided to utilize the provided `Zfinx` floating-point ext
code (see `sw/example/floating_point_test`).
==== **`Zbb`** Basic Bit-Manipulation Operations
The `Zbb` extension implements the _basic_ sub-set of the RISC-V bit-manipulation extensions `B`.
The official RISC-V specifications can be found here: https://github.com/riscv/riscv-bitmanip
The `Zbb` extension is implemented when the `CPU_EXTENSION_RISCV_Zbb` configuration
generic is _true_. In this case the following instructions are available:
* `andn`, `orn`, `xnor`
* `clz`, `ctz`, `cpop`
* `max`, `maxu`, `min`, `minu`
* `sext.b`, `sext.h`, `zext.h`
* `rol`, `ror`, `rori`
* `orc.b`, `rev8`
[TIP]
By default, the bit-manipulation unit uses an _iterative_ approach to compute shift-related operations
like `clz` and `rol`. To increase performance (at the cost of additional hardware resources) the
<<_fast_shift_en>> generic can be enabled to implement full-parallel logic (like barrel shifters) for all
shift-related `Zbb` instructions.
[WARNING]
The `Zbb` extension is frozen but not officially ratified yet. There is no
software support for this extension in the upstream GCC RISC-V port yet. However, an
intrinsic library is provided to utilize the provided `Zbb` extension from C-language
code (see `sw/example/bitmanip_test`).
==== **`Zicsr`** Control and Status Register Access / Privileged Architecture
The CSR access instructions as well as the exception and interrupt system (= the privileged architecture)
@ -759,12 +771,6 @@ configurations are presented in <<_cpu_performance>>.
| Memory access | `A` | `lr.w` `sc.w` | 4 + ML
| Multiplication | `M` | `mul` `mulh` `mulhsu` `mulhu` | 2+31+3; FAST_MULfootnote:[DSP-based multiplication; enabled via `FAST_MUL_EN`.]: 5
| Division | `M` | `div` `divu` `rem` `remu` | 22+32+4
| Bit-manipulation - arithmetic/logic | `B(Zbb)` | `sext.b` `sext.h` `min` `minu` `max` `maxu` `andn` `orn` `xnor` `zext`(pack) `rev8`(grevi) `orc.b`(gorci) | 3
| Bit-manipulation - shifts | `B(Zbb)` | `clz` `ctz` | 3 + 0..32
| Bit-manipulation - shifts | `B(Zbb)` | `cpop` | 3 + 32
| Bit-manipulation - shifts | `B(Zbb)` | `rol` `ror` `rori` | 3 + SA
| Bit-manipulation - single-bit | `B(Zbs)` | `sbset[i]` `sbclr[i]` `sbinv[i]` `sbext[i]` | 3
| Bit-manipulation - shifted-add | `B(Zba)` | `sh1add` `sh2add` `sh3add` | 3
| CSR access | `Zicsr` | `csrrw` `csrrs` `csrrc` `csrrwi` `csrrsi` `csrrci` | 4
| System | `I/E`+`Zicsr` | `ecall` `ebreak` | 4
| System | `I/E` | `fence` | 3
@ -778,10 +784,13 @@ configurations are presented in <<_cpu_performance>>.
| Floating-point - misc | `Zfinx` | `fsgnj.s` `fsgnjn.s` `fsgnjx.s` `fclass.s` | 12
| Floating-point - conversion | `Zfinx` | `fcvt.w.s` `fcvt.wu.s` | 47
| Floating-point - conversion | `Zfinx` | `fcvt.s.w` `fcvt.s.wu` | 48
| Basic bit-manip - logic | `Zbb` | `andn` `orn` `xnor` | 3
| Basic bit-manip - shift | `Zbb` | `clz` `ctz` `cpop` `rol` `ror` `rori` | 4+SA, FAST_SHIFT: 4
| Basic bit-manip - arith | `Zbb` | `max` `maxu` `min` `minu` | 3
| Basic bit-manip - misc | `Zbb` | `sext.b` `sext.h` `zext.h` `orc.b` `rev8` | 3
| Bit-manipulation - arithmetic/logic | `B(Zbb)` | `sext.b` `sext.h` `min` `minu` `max` `maxu` `andn` `orn` `xnor` `zext`(pack) `rev8`(grevi) `orc.b`(gorci) | 3
| Bit-manipulation - arithmetic/logic | `B(Zba)` | `sh1add` `sh2add` `sh3add` | 3
| Bit-manipulation - shifts | `B(Zbb)` | `clz` `ctz` | 3 + 0..32
| Bit-manipulation - shifts | `B(Zbb)` | `cpop` | 3 + 32
| Bit-manipulation - shifts | `B(Zbb)` | `rol` `ror` `rori` | 3 + SA
| Bit-manipulation - single-bit | `B(Zbs)` | `sbset[i]` `sbclr[i]` `sbinv[i]` `sbext[i]` | 3
| Bit-manipulation - shifted-add | `B(Zba)` | `sh1add` `sh2add` `sh3add` | 3
|=======================
[NOTE]

View file

@ -237,6 +237,18 @@ See section <<_a_atomic_memory_access>>.
|======
:sectnums!:
===== _CPU_EXTENSION_RISCV_B_
[cols="4,4,2"]
[frame="all",grid="none"]
|======
| **CPU_EXTENSION_RISCV_B** | _boolean_ | false
3+| Implement the `B` bit-manipulation sub-extension when _true_.
See section <<_b_bit_manipulation_operations>> for more information.
|======
:sectnums!:
===== _CPU_EXTENSION_RISCV_C_
@ -289,18 +301,6 @@ See section <<_u_less_privileged_user_mode>> for more information.
|======
:sectnums!:
===== _CPU_EXTENSION_RISCV_Zbb_
[cols="4,4,2"]
[frame="all",grid="none"]
|======
| **CPU_EXTENSION_RISCV_Zbb** | _boolean_ | false
3+| Implement the `Zbb` _basic_ bit-manipulation sub-extension when _true_.
See section <<_zbb_basic_bit_manipulation_operations>> for more information.
|======
:sectnums!:
===== _CPU_EXTENSION_RISCV_Zfinx_
@ -385,7 +385,7 @@ enabled (<<_cpu_extension_riscv_m>> or <<_cpu_extension_riscv_zmmul>> is _true_)
more hardware resources but completing within two clock cycles). If it is set _false_, the CPU uses a serial shifter
that only performs a single bit shift per cycle (requiring less hardware resources, but requires up to 32 clock
cycles to complete - depending on shift amount). **Note that this option also implements barrel shifters for _all_
shift-related operations of the <<_zbb_basic_bit_manipulation_operations>> extension.**
shift-related operations of the <<_b_bit_manipulation_operations>> extension.**
|======

View file

@ -47,7 +47,6 @@ and default clock speed) for correct operation.
| `0` | _SYSINFO_CPU_ZICSR_ | `Zicsr` extension (`I` sub-extension) available when set (via top's <<_cpu_extension_riscv_zicsr>> generic)
| `1` | _SYSINFO_CPU_ZIFENCEI_ | `Zifencei` extension (`I` sub-extension) available when set (via top's <<_cpu_extension_riscv_zifencei>> generic)
| `2` | _SYSINFO_CPU_ZMMUL_ | `Zmmul` extension (`M` sub-extension) available when set (via top's <<_cpu_extension_riscv_zmmul>> generic)
| `3` | _SYSINFO_CPU_ZBB_ | `Zbb` extension (`B` sub-extension) available when set (via top's <<_cpu_extension_riscv_zbb>> generic)
| `5` | _SYSINFO_CPU_ZFINX_ | `Zfinx` extension (`F` sub-/alternative-extension) available when set (via top's <<_cpu_extension_riscv_zfinx>> generic)
| `6` | _SYSINFO_CPU_ZXSCNT_ | Custom extension - _Small_ CPU counters: `[m]cycle` & `[m]instret` CSRs have less than 64-bit when set (via top's <<_cpu_cnt_width>> generic)
| `7` | _SYSINFO_CPU_ZXNOCNT_ | Custom extension - _NO_ CPU counters: `[m]cycle` & `[m]instret` CSRs are NOT available at all when set (via top's <<_cpu_cnt_width>> generic)

Binary file not shown.

Before

Width:  |  Height:  |  Size: 110 KiB

After

Width:  |  Height:  |  Size: 110 KiB

Before After
Before After

View file

@ -65,11 +65,11 @@ entity neorv32_cpu is
CPU_DEBUG_ADDR : std_ulogic_vector(31 downto 0); -- cpu debug mode start address
-- RISC-V CPU Extensions --
CPU_EXTENSION_RISCV_A : boolean; -- implement atomic extension?
CPU_EXTENSION_RISCV_B : boolean; -- implement bit-manipulation extension?
CPU_EXTENSION_RISCV_C : boolean; -- implement compressed extension?
CPU_EXTENSION_RISCV_E : boolean; -- implement embedded RF extension?
CPU_EXTENSION_RISCV_M : boolean; -- implement muld/div extension?
CPU_EXTENSION_RISCV_U : boolean; -- implement user mode extension?
CPU_EXTENSION_RISCV_Zbb : boolean; -- implement basic bit-manipulation sub-extension?
CPU_EXTENSION_RISCV_Zfinx : boolean; -- implement 32-bit floating-point extension (using INT reg!)
CPU_EXTENSION_RISCV_Zicsr : boolean; -- implement CSR system?
CPU_EXTENSION_RISCV_Zifencei : boolean; -- implement instruction stream sync.?
@ -170,8 +170,8 @@ begin
cond_sel_string_f(CPU_EXTENSION_RISCV_M, "M", "") &
cond_sel_string_f(CPU_EXTENSION_RISCV_A, "A", "") &
cond_sel_string_f(CPU_EXTENSION_RISCV_C, "C", "") &
cond_sel_string_f(CPU_EXTENSION_RISCV_B, "B", "") &
cond_sel_string_f(CPU_EXTENSION_RISCV_U, "U", "") &
cond_sel_string_f(CPU_EXTENSION_RISCV_Zbb, "_Zbb", "") &
cond_sel_string_f(CPU_EXTENSION_RISCV_Zicsr, "_Zicsr", "") &
cond_sel_string_f(CPU_EXTENSION_RISCV_Zifencei, "_Zifencei", "") &
cond_sel_string_f(CPU_EXTENSION_RISCV_Zfinx, "_Zfinx", "") &
@ -242,11 +242,11 @@ begin
CPU_DEBUG_ADDR => CPU_DEBUG_ADDR, -- cpu debug mode start address
-- RISC-V CPU Extensions --
CPU_EXTENSION_RISCV_A => CPU_EXTENSION_RISCV_A, -- implement atomic extension?
CPU_EXTENSION_RISCV_B => CPU_EXTENSION_RISCV_B, -- implement bit-manipulation extension?
CPU_EXTENSION_RISCV_C => CPU_EXTENSION_RISCV_C, -- implement compressed extension?
CPU_EXTENSION_RISCV_E => CPU_EXTENSION_RISCV_E, -- implement embedded RF extension?
CPU_EXTENSION_RISCV_M => CPU_EXTENSION_RISCV_M, -- implement mul/div extension?
CPU_EXTENSION_RISCV_U => CPU_EXTENSION_RISCV_U, -- implement user mode extension?
CPU_EXTENSION_RISCV_Zbb => CPU_EXTENSION_RISCV_Zbb, -- implement basic bit-manipulation sub-extension?
CPU_EXTENSION_RISCV_Zfinx => CPU_EXTENSION_RISCV_Zfinx, -- implement 32-bit floating-point extension (using INT reg!)
CPU_EXTENSION_RISCV_Zicsr => CPU_EXTENSION_RISCV_Zicsr, -- implement CSR system?
CPU_EXTENSION_RISCV_Zifencei => CPU_EXTENSION_RISCV_Zifencei, -- implement instruction stream sync.?
@ -335,8 +335,8 @@ begin
neorv32_cpu_alu_inst: neorv32_cpu_alu
generic map (
-- RISC-V CPU Extensions --
CPU_EXTENSION_RISCV_B => CPU_EXTENSION_RISCV_B, -- implement bit-manipulation extension?
CPU_EXTENSION_RISCV_M => CPU_EXTENSION_RISCV_M, -- implement mul/div extension?
CPU_EXTENSION_RISCV_Zbb => CPU_EXTENSION_RISCV_Zbb, -- implement basic bit-manipulation sub-extension?
CPU_EXTENSION_RISCV_Zmmul => CPU_EXTENSION_RISCV_Zmmul, -- implement multiply-only M sub-extension?
CPU_EXTENSION_RISCV_Zfinx => CPU_EXTENSION_RISCV_Zfinx, -- implement 32-bit floating-point extension (using INT reg!)
-- Extension Options --

View file

@ -44,8 +44,8 @@ use neorv32.neorv32_package.all;
entity neorv32_cpu_alu is
generic (
-- RISC-V CPU Extensions --
CPU_EXTENSION_RISCV_B : boolean; -- implement bit-manipulation extension?
CPU_EXTENSION_RISCV_M : boolean; -- implement mul/div extension?
CPU_EXTENSION_RISCV_Zbb : boolean; -- implement basic bit-manipulation sub-extension?
CPU_EXTENSION_RISCV_Zmmul : boolean; -- implement multiply-only M sub-extension?
CPU_EXTENSION_RISCV_Zfinx : boolean; -- implement 32-bit floating-point extension (using INT reg!)
-- Extension Options --
@ -293,32 +293,33 @@ begin
end generate;
-- Co-Processor 2: Bit-Manipulation Unit ('B'/'Zbb' Extension) ----------------------------
-- Co-Processor 2: Bit-Manipulation Unit ('B' Extension) ----------------------------------
-- -------------------------------------------------------------------------------------------
neorv32_cpu_cp_bitmanip_inst_true:
if (CPU_EXTENSION_RISCV_Zbb = true) generate
if (CPU_EXTENSION_RISCV_B = true) generate
neorv32_cpu_cp_bitmanip_inst: neorv32_cpu_cp_bitmanip
generic map (
FAST_SHIFT_EN => FAST_SHIFT_EN -- use barrel shifter for shift operations
)
port map (
-- global control --
clk_i => clk_i, -- global clock, rising edge
rstn_i => rstn_i, -- global reset, low-active, async
ctrl_i => ctrl_i, -- main control bus
start_i => cp_start(2), -- trigger operation
clk_i => clk_i, -- global clock, rising edge
rstn_i => rstn_i, -- global reset, low-active, async
ctrl_i => ctrl_i, -- main control bus
start_i => cp_start(2), -- trigger operation
-- data input --
cmp_i => cmp, -- comparator status
rs1_i => rs1_i, -- rf source 1
rs2_i => rs2_i, -- rf source 2
cmp_i => cmp, -- comparator status
rs1_i => rs1_i, -- rf source 1
rs2_i => rs2_i, -- rf source 2
shamt_i => opb(index_size_f(data_width_c)-1 downto 0), -- shift amount
-- result and status --
res_o => cp_result(2), -- operation result
valid_o => cp_valid(2) -- data output valid
res_o => cp_result(2), -- operation result
valid_o => cp_valid(2) -- data output valid
);
end generate;
neorv32_cpu_cp_bitmanip_inst_false:
if (CPU_EXTENSION_RISCV_Zbb = false) generate
if (CPU_EXTENSION_RISCV_B = false) generate
cp_result(2) <= (others => '0');
cp_valid(2) <= cp_start(2); -- to make sure CPU does not get stalled if there is an accidental access
end generate;

View file

@ -53,11 +53,11 @@ entity neorv32_cpu_control is
CPU_DEBUG_ADDR : std_ulogic_vector(31 downto 0); -- cpu debug mode start address
-- RISC-V CPU Extensions --
CPU_EXTENSION_RISCV_A : boolean; -- implement atomic extension?
CPU_EXTENSION_RISCV_B : boolean; -- implement bit-manipulation extension?
CPU_EXTENSION_RISCV_C : boolean; -- implement compressed extension?
CPU_EXTENSION_RISCV_E : boolean; -- implement embedded RF extension?
CPU_EXTENSION_RISCV_M : boolean; -- implement mul/div extension?
CPU_EXTENSION_RISCV_U : boolean; -- implement user mode extension?
CPU_EXTENSION_RISCV_Zbb : boolean; -- implement basic bit-manipulation sub-extension?
CPU_EXTENSION_RISCV_Zfinx : boolean; -- implement 32-bit floating-point extension (using INT reg!)
CPU_EXTENSION_RISCV_Zicsr : boolean; -- implement CSR system?
CPU_EXTENSION_RISCV_Zifencei : boolean; -- implement instruction stream sync.?
@ -860,6 +860,13 @@ begin
(execute_engine.i_reg(instr_funct3_msb_c downto instr_funct3_lsb_c) = "110") or -- ORN
(execute_engine.i_reg(instr_funct3_msb_c downto instr_funct3_lsb_c) = "100") -- XORN
)
) or
((execute_engine.i_reg(instr_funct7_msb_c downto instr_funct7_lsb_c) = "0010000") and
(
(execute_engine.i_reg(instr_funct3_msb_c downto instr_funct3_lsb_c) = "010") or -- SH1ADD
(execute_engine.i_reg(instr_funct3_msb_c downto instr_funct3_lsb_c) = "100") or -- SH2ADD
(execute_engine.i_reg(instr_funct3_msb_c downto instr_funct3_lsb_c) = "110") -- SH3ADD
)
) then
decode_aux.is_bitmanip_reg <= '1';
end if;
@ -1043,7 +1050,7 @@ begin
ctrl_nxt(ctrl_cp_id_msb_c downto ctrl_cp_id_lsb_c) <= cp_sel_muldiv_c; -- use MULDIV CP
ctrl_nxt(ctrl_alu_func1_c downto ctrl_alu_func0_c) <= alu_func_cmd_copro_c;
-- co-processor bit manipulation operation? --
elsif (CPU_EXTENSION_RISCV_Zbb = true) and
elsif (CPU_EXTENSION_RISCV_B = true) and
(((execute_engine.i_reg(instr_opcode_lsb_c+5) = opcode_alu_c(5)) and (decode_aux.is_bitmanip_reg = '1')) or -- register operation
((execute_engine.i_reg(instr_opcode_lsb_c+5) = opcode_alui_c(5)) and (decode_aux.is_bitmanip_imm = '1'))) then -- immediate operation
ctrl_nxt(ctrl_cp_id_msb_c downto ctrl_cp_id_lsb_c) <= cp_sel_bitmanip_c; -- use BITMANIP CP
@ -1066,7 +1073,7 @@ begin
(execute_engine.i_reg(instr_funct3_msb_c downto instr_funct3_lsb_c) = funct3_sr_c) or -- SR shift operation?
((CPU_EXTENSION_RISCV_M = true) and ((decode_aux.is_m_mul = '1') or (decode_aux.is_m_div = '1'))) or -- MUL/DIV
((CPU_EXTENSION_RISCV_Zmmul = true) and (decode_aux.is_m_mul = '1')) or -- MUL
((CPU_EXTENSION_RISCV_Zbb = true) and (
((CPU_EXTENSION_RISCV_B = true) and (
((execute_engine.i_reg(instr_opcode_lsb_c+5) = opcode_alu_c(5)) and (decode_aux.is_bitmanip_reg = '1')) or -- BITMANIP CP register operation?
((execute_engine.i_reg(instr_opcode_lsb_c+5) = opcode_alui_c(5)) and (decode_aux.is_bitmanip_imm = '1'))) -- BITMANIP CP immediate operation?
) then
@ -1435,7 +1442,7 @@ begin
illegal_instruction <= '1';
end if;
elsif (decode_aux.is_bitmanip_reg = '1') then -- bit manipulation
if (CPU_EXTENSION_RISCV_Zbb = false) then -- not implemented
if (CPU_EXTENSION_RISCV_B = false) then -- not implemented
illegal_instruction <= '1';
end if;
elsif ((execute_engine.i_reg(instr_funct3_msb_c downto instr_funct3_lsb_c) = funct3_subadd_c) or
@ -1455,7 +1462,7 @@ begin
when opcode_alui_c => -- check ALUI.funct7
-- ------------------------------------------------------------
if (decode_aux.is_bitmanip_imm = '1') then -- bit manipulation
if (CPU_EXTENSION_RISCV_Zbb = false) then -- not implemented
if (CPU_EXTENSION_RISCV_B = false) then -- not implemented
illegal_instruction <= '1';
end if;
elsif ((execute_engine.i_reg(instr_funct3_msb_c downto instr_funct3_lsb_c) = funct3_sll_c) and
@ -2503,6 +2510,7 @@ begin
csr.rdata(12) <= csr.mstatus_mpp(1); -- MPP: machine previous privilege mode high
when csr_misa_c => -- misa (r/-): ISA and extensions
csr.rdata(00) <= bool_to_ulogic_f(CPU_EXTENSION_RISCV_A); -- A CPU extension
csr.rdata(01) <= bool_to_ulogic_f(CPU_EXTENSION_RISCV_B); -- B CPU extension
csr.rdata(02) <= bool_to_ulogic_f(CPU_EXTENSION_RISCV_C); -- C CPU extension
csr.rdata(04) <= bool_to_ulogic_f(CPU_EXTENSION_RISCV_E); -- E CPU extension
csr.rdata(08) <= not bool_to_ulogic_f(CPU_EXTENSION_RISCV_E); -- I CPU extension (if not E)

View file

@ -7,6 +7,7 @@
-- # fixed value of 3 cycles latency (using barrel shifters). #
-- # #
-- # Supported sub-extensions (Zb*): #
-- # - Zba: Address generation instructions #
-- # - Zbb: Basic bit-manipulation instructions #
-- # ********************************************************************************************* #
-- # BSD 3-Clause License #
@ -61,6 +62,7 @@ entity neorv32_cpu_cp_bitmanip is
cmp_i : in std_ulogic_vector(1 downto 0); -- comparator status
rs1_i : in std_ulogic_vector(data_width_c-1 downto 0); -- rf source 1
rs2_i : in std_ulogic_vector(data_width_c-1 downto 0); -- rf source 2
shamt_i : in std_ulogic_vector(index_size_f(data_width_c)-1 downto 0); -- shift amount
-- result and status --
res_o : out std_ulogic_vector(data_width_c-1 downto 0); -- operation result
valid_o : out std_ulogic -- data output valid
@ -69,31 +71,40 @@ end neorv32_cpu_cp_bitmanip;
architecture neorv32_cpu_cp_bitmanip_rtl of neorv32_cpu_cp_bitmanip is
-- commands: logic with negate --
constant op_andn_c : natural := 0;
constant op_orn_c : natural := 1;
constant op_xnor_c : natural := 2;
-- commands: count leading/trailing zero bits --
constant op_clz_c : natural := 3;
constant op_ctz_c : natural := 4;
-- commands: count population --
constant op_cpop_c : natural := 5;
-- commands: integer minimum/maximum --
constant op_max_c : natural := 6; -- signed/unsigned
constant op_min_c : natural := 7; -- signed/unsigned
-- commands: sign- and zero-extension --
constant op_sextb_c : natural := 8;
constant op_sexth_c : natural := 9;
constant op_zexth_c : natural := 10;
-- commands: bitwise rotation --
constant op_rol_c : natural := 11;
constant op_ror_c : natural := 12; -- rori
-- commands: or-combine --
constant op_orcb_c : natural := 13;
-- commands: byte-reverse --
constant op_rev8_c : natural := 14;
-- Sub-extension configuration --
constant zbb_en_c : boolean := true;
constant zba_en_c : boolean := true;
-- --------------------------- --
-- commands: Zbb - logic with negate --
constant op_andn_c : natural := 0;
constant op_orn_c : natural := 1;
constant op_xnor_c : natural := 2;
-- commands: Zbb - count leading/trailing zero bits --
constant op_clz_c : natural := 3;
constant op_ctz_c : natural := 4;
-- commands: Zbb - count population --
constant op_cpop_c : natural := 5;
-- commands: Zbb - integer minimum/maximum --
constant op_max_c : natural := 6; -- signed/unsigned
constant op_min_c : natural := 7; -- signed/unsigned
-- commands: Zbb - sign- and zero-extension --
constant op_sextb_c : natural := 8;
constant op_sexth_c : natural := 9;
constant op_zexth_c : natural := 10;
-- commands: Zbb - bitwise rotation --
constant op_rol_c : natural := 11;
constant op_ror_c : natural := 12; -- rori
-- commands: Zbb - or-combine --
constant op_orcb_c : natural := 13;
-- commands: Zbb - byte-reverse --
constant op_rev8_c : natural := 14;
-- commands: Zba - shifted add --
constant op_sh1add_c : natural := 15;
constant op_sh2add_c : natural := 16;
constant op_sh3add_c : natural := 17;
--
constant op_width_c : natural := 15;
constant op_width_c : natural := 18;
-- controller --
type ctrl_state_t is (S_IDLE, S_START_SHIFT, S_BUSY_SHIFT);
@ -104,11 +115,9 @@ architecture neorv32_cpu_cp_bitmanip_rtl of neorv32_cpu_cp_bitmanip is
-- operand buffers --
signal rs1_reg : std_ulogic_vector(data_width_c-1 downto 0);
signal rs2_reg : std_ulogic_vector(data_width_c-1 downto 0);
signal sha_reg : std_ulogic_vector(index_size_f(data_width_c)-1 downto 0);
signal less_ff : std_ulogic;
-- shift amount (immediate or register) --
signal shamt : std_ulogic_vector(index_size_f(data_width_c)-1 downto 0);
-- serial shifter --
type shifter_t is record
start : std_ulogic;
@ -128,32 +137,50 @@ architecture neorv32_cpu_cp_bitmanip_rtl of neorv32_cpu_cp_bitmanip is
type res_t is array (0 to op_width_c-1) of std_ulogic_vector(data_width_c-1 downto 0);
signal res_int, res_out : res_t;
-- shifted-add unit --
signal adder_core : std_ulogic_vector(data_width_c-1 downto 0);
begin
-- Sub-Extension Configuration ------------------------------------------------------------
-- -------------------------------------------------------------------------------------------
assert false report
"Implementing bit-manipulation (B) sub-extensions: " &
cond_sel_string_f(zbb_en_c, "Zbb", "") &
cond_sel_string_f(zba_en_c, "Zba", "") &
""
severity note;
-- Instruction Decoding (One-Hot) ---------------------------------------------------------
-- -------------------------------------------------------------------------------------------
-- a minimal decoding logic is used here -> just to distinguish between B.Zbb instructions
-- a more specific decoding and instruction check is done by the CPU control unit
-- Zbb - Basic bit-manipulation instructions --
cmd(op_andn_c) <= '1' when (ctrl_i(ctrl_ir_funct12_10_c downto ctrl_ir_funct12_9_c) = "10") and (ctrl_i(ctrl_ir_funct3_1_c downto ctrl_ir_funct3_0_c) = "11") else '0';
cmd(op_orn_c) <= '1' when (ctrl_i(ctrl_ir_funct12_10_c downto ctrl_ir_funct12_9_c) = "10") and (ctrl_i(ctrl_ir_funct3_1_c downto ctrl_ir_funct3_0_c) = "10") else '0';
cmd(op_xnor_c) <= '1' when (ctrl_i(ctrl_ir_funct12_10_c downto ctrl_ir_funct12_9_c) = "10") and (ctrl_i(ctrl_ir_funct3_1_c downto ctrl_ir_funct3_0_c) = "00") else '0';
cmd(op_andn_c) <= '1' when (zbb_en_c = true) and (ctrl_i(ctrl_ir_funct12_10_c downto ctrl_ir_funct12_9_c) = "10") and (ctrl_i(ctrl_ir_funct3_1_c downto ctrl_ir_funct3_0_c) = "11") else '0';
cmd(op_orn_c) <= '1' when (zbb_en_c = true) and (ctrl_i(ctrl_ir_funct12_10_c downto ctrl_ir_funct12_9_c) = "10") and (ctrl_i(ctrl_ir_funct3_1_c downto ctrl_ir_funct3_0_c) = "10") else '0';
cmd(op_xnor_c) <= '1' when (zbb_en_c = true) and (ctrl_i(ctrl_ir_funct12_10_c downto ctrl_ir_funct12_9_c) = "10") and (ctrl_i(ctrl_ir_funct3_1_c downto ctrl_ir_funct3_0_c) = "00") else '0';
--
cmd(op_max_c) <= '1' when (ctrl_i(ctrl_ir_funct12_10_c downto ctrl_ir_funct12_9_c) = "00") and (ctrl_i(ctrl_ir_funct12_5_c) = '1') and (ctrl_i(ctrl_ir_funct3_1_c) = '1') else '0';
cmd(op_min_c) <= '1' when (ctrl_i(ctrl_ir_funct12_10_c downto ctrl_ir_funct12_9_c) = "00") and (ctrl_i(ctrl_ir_funct12_5_c) = '1') and (ctrl_i(ctrl_ir_funct3_1_c) = '0') else '0';
cmd(op_zexth_c) <= '1' when (ctrl_i(ctrl_ir_funct12_10_c downto ctrl_ir_funct12_9_c) = "00") and (ctrl_i(ctrl_ir_funct12_5_c) = '0') else '0';
cmd(op_max_c) <= '1' when (zbb_en_c = true) and (ctrl_i(ctrl_ir_funct12_10_c downto ctrl_ir_funct12_9_c) = "00") and (ctrl_i(ctrl_ir_funct12_5_c) = '1') and (ctrl_i(ctrl_ir_funct3_1_c) = '1') else '0';
cmd(op_min_c) <= '1' when (zbb_en_c = true) and (ctrl_i(ctrl_ir_funct12_10_c downto ctrl_ir_funct12_9_c) = "00") and (ctrl_i(ctrl_ir_funct12_5_c) = '1') and (ctrl_i(ctrl_ir_funct3_1_c) = '0') else '0';
cmd(op_zexth_c) <= '1' when (zbb_en_c = true) and (ctrl_i(ctrl_ir_funct12_10_c downto ctrl_ir_funct12_9_c) = "00") and (ctrl_i(ctrl_ir_funct12_5_c) = '0') else '0';
--
cmd(op_orcb_c) <= '1' when (ctrl_i(ctrl_ir_funct12_10_c downto ctrl_ir_funct12_9_c) = "01") else '0';
cmd(op_orcb_c) <= '1' when (zbb_en_c = true) and (ctrl_i(ctrl_ir_funct12_10_c downto ctrl_ir_funct12_9_c) = "01") and (ctrl_i(ctrl_ir_funct12_7_c) = '1') else '0';
--
cmd(op_clz_c) <= '1' when (ctrl_i(ctrl_ir_funct12_10_c downto ctrl_ir_funct12_9_c) = "11") and (ctrl_i(ctrl_ir_funct12_7_c) = '0') and (ctrl_i(ctrl_ir_funct12_2_c downto ctrl_ir_funct12_0_c) = "000") else '0';
cmd(op_ctz_c) <= '1' when (ctrl_i(ctrl_ir_funct12_10_c downto ctrl_ir_funct12_9_c) = "11") and (ctrl_i(ctrl_ir_funct12_7_c) = '0') and (ctrl_i(ctrl_ir_funct12_2_c downto ctrl_ir_funct12_0_c) = "001") else '0';
cmd(op_cpop_c) <= '1' when (ctrl_i(ctrl_ir_funct12_10_c downto ctrl_ir_funct12_9_c) = "11") and (ctrl_i(ctrl_ir_funct12_7_c) = '0') and (ctrl_i(ctrl_ir_funct12_2_c downto ctrl_ir_funct12_0_c) = "010") else '0';
cmd(op_sextb_c) <= '1' when (ctrl_i(ctrl_ir_funct12_10_c downto ctrl_ir_funct12_9_c) = "11") and (ctrl_i(ctrl_ir_funct12_7_c) = '0') and (ctrl_i(ctrl_ir_funct3_2_c) = '0') and (ctrl_i(ctrl_ir_funct12_2_c downto ctrl_ir_funct12_0_c) = "100") else '0';
cmd(op_sexth_c) <= '1' when (ctrl_i(ctrl_ir_funct12_10_c downto ctrl_ir_funct12_9_c) = "11") and (ctrl_i(ctrl_ir_funct12_7_c) = '0') and (ctrl_i(ctrl_ir_funct3_2_c) = '0') and (ctrl_i(ctrl_ir_funct12_2_c downto ctrl_ir_funct12_0_c) = "101") else '0';
cmd(op_rol_c) <= '1' when (ctrl_i(ctrl_ir_funct12_10_c downto ctrl_ir_funct12_9_c) = "11") and (ctrl_i(ctrl_ir_funct12_7_c) = '0') and (ctrl_i(ctrl_ir_funct3_2_c downto ctrl_ir_funct3_0_c) = "001") and (ctrl_i(ctrl_ir_opcode7_5_c) = '1') else '0';
cmd(op_ror_c) <= '1' when (ctrl_i(ctrl_ir_funct12_10_c downto ctrl_ir_funct12_9_c) = "11") and (ctrl_i(ctrl_ir_funct12_7_c) = '0') and (ctrl_i(ctrl_ir_funct3_2_c downto ctrl_ir_funct3_0_c) = "101") else '0';
cmd(op_rev8_c) <= '1' when (ctrl_i(ctrl_ir_funct12_10_c downto ctrl_ir_funct12_9_c) = "11") and (ctrl_i(ctrl_ir_funct12_7_c) = '1') else '0';
cmd(op_clz_c) <= '1' when (zbb_en_c = true) and (ctrl_i(ctrl_ir_funct12_10_c downto ctrl_ir_funct12_9_c) = "11") and (ctrl_i(ctrl_ir_funct12_7_c) = '0') and (ctrl_i(ctrl_ir_funct12_2_c downto ctrl_ir_funct12_0_c) = "000") else '0';
cmd(op_ctz_c) <= '1' when (zbb_en_c = true) and (ctrl_i(ctrl_ir_funct12_10_c downto ctrl_ir_funct12_9_c) = "11") and (ctrl_i(ctrl_ir_funct12_7_c) = '0') and (ctrl_i(ctrl_ir_funct12_2_c downto ctrl_ir_funct12_0_c) = "001") else '0';
cmd(op_cpop_c) <= '1' when (zbb_en_c = true) and (ctrl_i(ctrl_ir_funct12_10_c downto ctrl_ir_funct12_9_c) = "11") and (ctrl_i(ctrl_ir_funct12_7_c) = '0') and (ctrl_i(ctrl_ir_funct12_2_c downto ctrl_ir_funct12_0_c) = "010") else '0';
cmd(op_sextb_c) <= '1' when (zbb_en_c = true) and (ctrl_i(ctrl_ir_funct12_10_c downto ctrl_ir_funct12_9_c) = "11") and (ctrl_i(ctrl_ir_funct12_7_c) = '0') and (ctrl_i(ctrl_ir_funct3_2_c) = '0') and (ctrl_i(ctrl_ir_funct12_2_c downto ctrl_ir_funct12_0_c) = "100") else '0';
cmd(op_sexth_c) <= '1' when (zbb_en_c = true) and (ctrl_i(ctrl_ir_funct12_10_c downto ctrl_ir_funct12_9_c) = "11") and (ctrl_i(ctrl_ir_funct12_7_c) = '0') and (ctrl_i(ctrl_ir_funct3_2_c) = '0') and (ctrl_i(ctrl_ir_funct12_2_c downto ctrl_ir_funct12_0_c) = "101") else '0';
cmd(op_rol_c) <= '1' when (zbb_en_c = true) and (ctrl_i(ctrl_ir_funct12_10_c downto ctrl_ir_funct12_9_c) = "11") and (ctrl_i(ctrl_ir_funct12_7_c) = '0') and (ctrl_i(ctrl_ir_funct3_2_c downto ctrl_ir_funct3_0_c) = "001") and (ctrl_i(ctrl_ir_opcode7_5_c) = '1') else '0';
cmd(op_ror_c) <= '1' when (zbb_en_c = true) and (ctrl_i(ctrl_ir_funct12_10_c downto ctrl_ir_funct12_9_c) = "11") and (ctrl_i(ctrl_ir_funct12_7_c) = '0') and (ctrl_i(ctrl_ir_funct3_2_c downto ctrl_ir_funct3_0_c) = "101") else '0';
cmd(op_rev8_c) <= '1' when (zbb_en_c = true) and (ctrl_i(ctrl_ir_funct12_10_c downto ctrl_ir_funct12_9_c) = "11") and (ctrl_i(ctrl_ir_funct12_7_c) = '1') else '0';
-- Zba - Address generation instructions --
cmd(op_sh1add_c) <= '1' when (zba_en_c = true) and (ctrl_i(ctrl_ir_funct12_10_c downto ctrl_ir_funct12_9_c) = "01") and (ctrl_i(ctrl_ir_funct12_7_c) = '0') and (ctrl_i(ctrl_ir_funct3_2_c downto ctrl_ir_funct3_1_c) = "01") else '0';
cmd(op_sh2add_c) <= '1' when (zba_en_c = true) and (ctrl_i(ctrl_ir_funct12_10_c downto ctrl_ir_funct12_9_c) = "01") and (ctrl_i(ctrl_ir_funct12_7_c) = '0') and (ctrl_i(ctrl_ir_funct3_2_c downto ctrl_ir_funct3_1_c) = "10") else '0';
cmd(op_sh3add_c) <= '1' when (zba_en_c = true) and (ctrl_i(ctrl_ir_funct12_10_c downto ctrl_ir_funct12_9_c) = "01") and (ctrl_i(ctrl_ir_funct12_7_c) = '0') and (ctrl_i(ctrl_ir_funct3_2_c downto ctrl_ir_funct3_1_c) = "11") else '0';
-- Co-Processor Controller ----------------------------------------------------------------
@ -165,6 +192,7 @@ begin
cmd_buf <= (others => def_rst_val_c);
rs1_reg <= (others => def_rst_val_c);
rs2_reg <= (others => def_rst_val_c);
sha_reg <= (others => def_rst_val_c);
less_ff <= def_rst_val_c;
shifter.start <= '0';
valid <= '0';
@ -183,6 +211,7 @@ begin
cmd_buf <= cmd;
rs1_reg <= rs1_i;
rs2_reg <= rs2_i;
sha_reg <= shamt_i;
if ((cmd(op_clz_c) or cmd(op_ctz_c) or cmd(op_cpop_c) or cmd(op_ror_c) or cmd(op_rol_c)) = '1') then -- multi-cycle shift operation
if (FAST_SHIFT_EN = false) then -- default: iterative computation
shifter.start <= '1';
@ -216,13 +245,6 @@ begin
end process coprocessor_ctrl;
-- Shift Amount ---------------------------------------------------------------------------
-- -------------------------------------------------------------------------------------------
-- we could also use ALU's internal operand B - but we are having a local version here in order to allow
-- better logic combination inside the ALU (since that is the critical path of the CPU)
shamt <= ctrl_i(ctrl_ir_funct12_0_c+shamt'left downto ctrl_ir_funct12_0_c) when (ctrl_i(ctrl_ir_opcode7_5_c) = '0') else rs2_reg(shamt'left downto 0);
-- Shifter Function Core (iterative: small but slow) --------------------------------------
-- -------------------------------------------------------------------------------------------
serial_shifter:
@ -249,7 +271,7 @@ begin
shifter.cnt_max <= (others => '0');
shifter.cnt_max(shifter.cnt_max'left) <= '1';
else
shifter.cnt_max <= '0' & shamt;
shifter.cnt_max <= '0' & sha_reg;
end if;
shifter.bcnt <= (others => '0');
elsif (shifter.run = '1') then -- right shifts only
@ -313,7 +335,7 @@ begin
-- barrel shifter array --
barrel_shifter_async:
if (FAST_SHIFT_EN = true) generate
shifter_unit_async: process(rs1_reg, shamt, cmd_buf, bs_level)
shifter_unit_async: process(rs1_reg, sha_reg, cmd_buf, bs_level)
begin
-- input level: convert left shifts to right shifts --
if (cmd_buf(op_rol_c) = '1') then -- is left shift?
@ -324,7 +346,7 @@ begin
-- shifter array --
for i in index_size_f(data_width_c)-1 downto 0 loop
if (shamt(i) = '1') then
if (sha_reg(i) = '1') then
bs_level(i)(data_width_c-1 downto data_width_c-(2**i)) <= bs_level(i+1)((2**i)-1 downto 0);
bs_level(i)((data_width_c-(2**i))-1 downto 0) <= bs_level(i+1)(data_width_c-1 downto 2**i);
else
@ -335,6 +357,21 @@ begin
end generate;
-- Shifted-Add Core -----------------------------------------------------------------------
-- -------------------------------------------------------------------------------------------
shift_adder: process(rs1_reg, rs2_reg, ctrl_i)
variable opb_v : std_ulogic_vector(data_width_c-1 downto 0);
begin
case ctrl_i(ctrl_ir_funct3_2_c downto ctrl_ir_funct3_1_c) is
when "01" => opb_v := rs1_reg(rs1_reg'left-1 downto 0) & '0'; -- << 1
when "10" => opb_v := rs1_reg(rs1_reg'left-2 downto 0) & "00"; -- << 2
when "11" => opb_v := rs1_reg(rs1_reg'left-3 downto 0) & "000"; -- << 3
when others => opb_v := rs1_reg(rs1_reg'left-1 downto 0) & '0'; -- undefined
end case;
adder_core <= std_ulogic_vector(unsigned(rs2_reg) + unsigned(opb_v));
end process shift_adder;
-- Operation Results ----------------------------------------------------------------------
-- -------------------------------------------------------------------------------------------
-- logic with negate --
@ -376,6 +413,11 @@ begin
-- reversal.8 (byte swap) --
res_int(op_rev8_c) <= bswap32_f(rs1_reg);
-- address generation instructions --
res_int(op_sh1add_c) <= adder_core;
res_int(op_sh2add_c) <= (others => '0'); -- unused/redundant
res_int(op_sh3add_c) <= (others => '0'); -- unused/redundant
-- Output Selector ------------------------------------------------------------------------
-- -------------------------------------------------------------------------------------------
@ -394,6 +436,10 @@ begin
res_out(op_rol_c) <= res_int(op_rol_c) when (cmd_buf(op_rol_c) = '1') else (others => '0');
res_out(op_orcb_c) <= res_int(op_orcb_c) when (cmd_buf(op_orcb_c) = '1') else (others => '0');
res_out(op_rev8_c) <= res_int(op_rev8_c) when (cmd_buf(op_rev8_c) = '1') else (others => '0');
--
res_out(op_sh1add_c) <= res_int(op_sh1add_c) when ((cmd_buf(op_sh1add_c) or cmd_buf(op_sh2add_c) or cmd_buf(op_sh3add_c)) = '1') else (others => '0');
res_out(op_sh2add_c) <= (others => '0'); -- unused/redundant
res_out(op_sh3add_c) <= (others => '0'); -- unused/redundant
-- Output Gate ----------------------------------------------------------------------------
@ -410,7 +456,8 @@ begin
res_out(op_min_c) or -- res_out(op_max_c) is unused here
res_out(op_sextb_c) or res_out(op_sexth_c) or res_out(op_zexth_c) or
res_out(op_ror_c) or res_out(op_rol_c) or
res_out(op_orcb_c) or res_out(op_rev8_c);
res_out(op_orcb_c) or res_out(op_rev8_c) or
res_out(op_sh1add_c); -- res_out(op_sh2add_c) and res_out(op_sh3add_c) are unused here
end if;
end if;
end process output_gate;

View file

@ -64,7 +64,7 @@ package neorv32_package is
-- Architecture Constants (do not modify!) ------------------------------------------------
-- -------------------------------------------------------------------------------------------
constant data_width_c : natural := 32; -- native data path width - do not change!
constant hw_version_c : std_ulogic_vector(31 downto 0) := x"01060210"; -- no touchy!
constant hw_version_c : std_ulogic_vector(31 downto 0) := x"01060211"; -- no touchy!
constant archid_c : natural := 19; -- official NEORV32 architecture ID - hands off!
-- External Interface Types ---------------------------------------------------------------
@ -899,11 +899,11 @@ package neorv32_package is
ON_CHIP_DEBUGGER_EN : boolean := false; -- implement on-chip debugger
-- RISC-V CPU Extensions --
CPU_EXTENSION_RISCV_A : boolean := false; -- implement atomic extension?
CPU_EXTENSION_RISCV_B : boolean := false; -- implement bit-manipulation extension?
CPU_EXTENSION_RISCV_C : boolean := false; -- implement compressed extension?
CPU_EXTENSION_RISCV_E : boolean := false; -- implement embedded RF extension?
CPU_EXTENSION_RISCV_M : boolean := false; -- implement mul/div extension?
CPU_EXTENSION_RISCV_U : boolean := false; -- implement user mode extension?
CPU_EXTENSION_RISCV_Zbb : boolean := false; -- implement basic bit-manipulation sub-extension?
CPU_EXTENSION_RISCV_Zfinx : boolean := false; -- implement 32-bit floating-point extension (using INT regs!)
CPU_EXTENSION_RISCV_Zicsr : boolean := true; -- implement CSR system?
CPU_EXTENSION_RISCV_Zifencei : boolean := false; -- implement instruction stream sync.?
@ -1049,11 +1049,11 @@ package neorv32_package is
CPU_DEBUG_ADDR : std_ulogic_vector(31 downto 0); -- cpu debug mode start address
-- RISC-V CPU Extensions --
CPU_EXTENSION_RISCV_A : boolean; -- implement atomic extension?
CPU_EXTENSION_RISCV_B : boolean; -- implement bit-manipulation extension?
CPU_EXTENSION_RISCV_C : boolean; -- implement compressed extension?
CPU_EXTENSION_RISCV_E : boolean; -- implement embedded RF extension?
CPU_EXTENSION_RISCV_M : boolean; -- implement mul/div extension?
CPU_EXTENSION_RISCV_U : boolean; -- implement user mode extension?
CPU_EXTENSION_RISCV_Zbb : boolean; -- implement basic bit-manipulation sub-extension?
CPU_EXTENSION_RISCV_Zfinx : boolean; -- implement 32-bit floating-point extension (using INT reg!)
CPU_EXTENSION_RISCV_Zicsr : boolean; -- implement CSR system?
CPU_EXTENSION_RISCV_Zifencei : boolean; -- implement instruction stream sync.?
@ -1123,11 +1123,11 @@ package neorv32_package is
CPU_DEBUG_ADDR : std_ulogic_vector(31 downto 0); -- cpu debug mode start address
-- RISC-V CPU Extensions --
CPU_EXTENSION_RISCV_A : boolean; -- implement atomic extension?
CPU_EXTENSION_RISCV_B : boolean; -- implement bit-manipulation extension?
CPU_EXTENSION_RISCV_C : boolean; -- implement compressed extension?
CPU_EXTENSION_RISCV_E : boolean; -- implement embedded RF extension?
CPU_EXTENSION_RISCV_M : boolean; -- implement mul/div extension?
CPU_EXTENSION_RISCV_U : boolean; -- implement user mode extension?
CPU_EXTENSION_RISCV_Zbb : boolean; -- implement basic bit-manipulation sub-extension?
CPU_EXTENSION_RISCV_Zfinx : boolean; -- implement 32-bit floating-point extension (using INT reg!)
CPU_EXTENSION_RISCV_Zicsr : boolean; -- implement CSR system?
CPU_EXTENSION_RISCV_Zifencei : boolean; -- implement instruction stream sync.?
@ -1213,8 +1213,8 @@ package neorv32_package is
component neorv32_cpu_alu
generic (
-- RISC-V CPU Extensions --
CPU_EXTENSION_RISCV_B : boolean; -- implement bit-manipulation extension?
CPU_EXTENSION_RISCV_M : boolean; -- implement mul/div extension?
CPU_EXTENSION_RISCV_Zbb : boolean; -- implement basic bit-manipulation sub-extension?
CPU_EXTENSION_RISCV_Zmmul : boolean; -- implement multiply-only M sub-extension?
CPU_EXTENSION_RISCV_Zfinx : boolean; -- implement 32-bit floating-point extension (using INT reg!)
-- Extension Options --
@ -1289,7 +1289,7 @@ package neorv32_package is
-- -------------------------------------------------------------------------------------------
component neorv32_cpu_cp_bitmanip is
generic (
FAST_SHIFT_EN : boolean -- use barrel shifter for shift operations
FAST_SHIFT_EN : boolean -- use barrel shifter for shift operations
);
port (
-- global control --
@ -1301,6 +1301,7 @@ package neorv32_package is
cmp_i : in std_ulogic_vector(1 downto 0); -- comparator status
rs1_i : in std_ulogic_vector(data_width_c-1 downto 0); -- rf source 1
rs2_i : in std_ulogic_vector(data_width_c-1 downto 0); -- rf source 2
shamt_i : in std_ulogic_vector(index_size_f(data_width_c)-1 downto 0); -- shift amount
-- result and status --
res_o : out std_ulogic_vector(data_width_c-1 downto 0); -- operation result
valid_o : out std_ulogic -- data output valid
@ -1902,7 +1903,6 @@ package neorv32_package is
CLOCK_FREQUENCY : natural; -- clock frequency of clk_i in Hz
INT_BOOTLOADER_EN : boolean; -- boot configuration: true = boot explicit bootloader; false = boot from int/ext (I)MEM
-- RISC-V CPU Extensions --
CPU_EXTENSION_RISCV_Zbb : boolean; -- implement basic bit-manipulation sub-extension?
CPU_EXTENSION_RISCV_Zfinx : boolean; -- implement 32-bit floating-point extension (using INT reg!)
CPU_EXTENSION_RISCV_Zicsr : boolean; -- implement CSR system?
CPU_EXTENSION_RISCV_Zifencei : boolean; -- implement instruction stream sync.?

View file

@ -48,7 +48,6 @@ entity neorv32_sysinfo is
CLOCK_FREQUENCY : natural; -- clock frequency of clk_i in Hz
INT_BOOTLOADER_EN : boolean; -- boot configuration: true = boot explicit bootloader; false = boot from int/ext (I)MEM
-- RISC-V CPU Extensions --
CPU_EXTENSION_RISCV_Zbb : boolean; -- implement basic bit-manipulation sub-extension?
CPU_EXTENSION_RISCV_Zfinx : boolean; -- implement 32-bit floating-point extension (using INT reg!)
CPU_EXTENSION_RISCV_Zicsr : boolean; -- implement CSR system?
CPU_EXTENSION_RISCV_Zifencei : boolean; -- implement instruction stream sync.?
@ -139,9 +138,8 @@ begin
sysinfo_mem(1)(00) <= bool_to_ulogic_f(CPU_EXTENSION_RISCV_Zicsr); -- Zicsr
sysinfo_mem(1)(01) <= bool_to_ulogic_f(CPU_EXTENSION_RISCV_Zifencei); -- Zifencei
sysinfo_mem(1)(02) <= bool_to_ulogic_f(CPU_EXTENSION_RISCV_Zmmul); -- Zmmul
sysinfo_mem(1)(03) <= bool_to_ulogic_f(CPU_EXTENSION_RISCV_Zbb); -- Zbb
--
sysinfo_mem(1)(04) <= '0'; -- reserved
sysinfo_mem(1)(04 downto 03) <= (others => '0'); -- reserved
--
sysinfo_mem(1)(05) <= bool_to_ulogic_f(CPU_EXTENSION_RISCV_Zfinx); -- Zfinx ("F-alternative")
sysinfo_mem(1)(07 downto 06) <= "00" when (CPU_CNT_WIDTH = 64) else "10" when (CPU_CNT_WIDTH = 0) else "01"; -- CPU counter size: Zxscnt | Zxnocnt

View file

@ -56,11 +56,11 @@ entity neorv32_top is
-- RISC-V CPU Extensions --
CPU_EXTENSION_RISCV_A : boolean := false; -- implement atomic extension?
CPU_EXTENSION_RISCV_B : boolean := false; -- implement bit-manipulation extension?
CPU_EXTENSION_RISCV_C : boolean := false; -- implement compressed extension?
CPU_EXTENSION_RISCV_E : boolean := false; -- implement embedded RF extension?
CPU_EXTENSION_RISCV_M : boolean := false; -- implement mul/div extension?
CPU_EXTENSION_RISCV_U : boolean := false; -- implement user mode extension?
CPU_EXTENSION_RISCV_Zbb : boolean := false; -- implement basic bit-manipulation sub-extension?
CPU_EXTENSION_RISCV_Zfinx : boolean := false; -- implement 32-bit floating-point extension (using INT regs!)
CPU_EXTENSION_RISCV_Zicsr : boolean := true; -- implement CSR system?
CPU_EXTENSION_RISCV_Zifencei : boolean := false; -- implement instruction stream sync.?
@ -452,11 +452,11 @@ begin
CPU_DEBUG_ADDR => dm_base_c, -- cpu debug mode start address
-- RISC-V CPU Extensions --
CPU_EXTENSION_RISCV_A => CPU_EXTENSION_RISCV_A, -- implement atomic extension?
CPU_EXTENSION_RISCV_B => CPU_EXTENSION_RISCV_B, -- implement bit-manipulation extension?
CPU_EXTENSION_RISCV_C => CPU_EXTENSION_RISCV_C, -- implement compressed extension?
CPU_EXTENSION_RISCV_E => CPU_EXTENSION_RISCV_E, -- implement embedded RF extension?
CPU_EXTENSION_RISCV_M => CPU_EXTENSION_RISCV_M, -- implement muld/div extension?
CPU_EXTENSION_RISCV_U => CPU_EXTENSION_RISCV_U, -- implement user mode extension?
CPU_EXTENSION_RISCV_Zbb => CPU_EXTENSION_RISCV_Zbb, -- implement basic bit-manipulation sub-extension?
CPU_EXTENSION_RISCV_Zfinx => CPU_EXTENSION_RISCV_Zfinx, -- implement 32-bit floating-point extension (using INT reg!)
CPU_EXTENSION_RISCV_Zicsr => CPU_EXTENSION_RISCV_Zicsr, -- implement CSR system?
CPU_EXTENSION_RISCV_Zifencei => CPU_EXTENSION_RISCV_Zifencei, -- implement instruction stream sync.?
@ -1347,7 +1347,6 @@ begin
CLOCK_FREQUENCY => CLOCK_FREQUENCY, -- clock frequency of clk_i in Hz
INT_BOOTLOADER_EN => INT_BOOTLOADER_EN, -- implement processor-internal bootloader?
-- RISC-V CPU Extensions --
CPU_EXTENSION_RISCV_Zbb => CPU_EXTENSION_RISCV_Zbb, -- implement basic bit-manipulation sub-extension?
CPU_EXTENSION_RISCV_Zfinx => CPU_EXTENSION_RISCV_Zfinx, -- implement 32-bit floating-point extension (using INT reg!)
CPU_EXTENSION_RISCV_Zicsr => CPU_EXTENSION_RISCV_Zicsr, -- implement CSR system?
CPU_EXTENSION_RISCV_Zifencei => CPU_EXTENSION_RISCV_Zifencei, -- implement instruction stream sync.?

View file

@ -98,10 +98,10 @@ architecture neorv32_twi_rtl of neorv32_twi is
signal twi_clk_halt : std_ulogic;
-- twi transceiver core --
signal ctrl : std_ulogic_vector(7 downto 0); -- unit's control register
signal arbiter : std_ulogic_vector(2 downto 0);
signal twi_bitcnt : std_ulogic_vector(3 downto 0);
signal twi_rtx_sreg : std_ulogic_vector(8 downto 0); -- main rx/tx shift reg
signal ctrl : std_ulogic_vector(7 downto 0); -- unit's control register
signal arbiter : std_ulogic_vector(2 downto 0);
signal bitcnt : std_ulogic_vector(3 downto 0);
signal rtx_sreg : std_ulogic_vector(8 downto 0); -- main rx/tx shift reg
-- tri-state I/O --
signal twi_sda_i_ff0, twi_sda_i_ff1 : std_ulogic; -- sda input sync
@ -142,10 +142,10 @@ begin
data_o(ctrl_twi_mack_c) <= ctrl(ctrl_twi_mack_c);
data_o(ctrl_twi_cksten_c) <= ctrl(ctrl_twi_cksten_c);
--
data_o(ctrl_twi_ack_c) <= not twi_rtx_sreg(0);
data_o(ctrl_twi_ack_c) <= not rtx_sreg(0);
data_o(ctrl_twi_busy_c) <= arbiter(1) or arbiter(0);
else -- twi_rtx_addr_c =>
data_o(7 downto 0) <= twi_rtx_sreg(8 downto 1);
data_o(7 downto 0) <= rtx_sreg(8 downto 1);
end if;
end if;
@ -166,7 +166,7 @@ begin
begin
if rising_edge(clk_i) then
if (arbiter(2) = '0') or (arbiter = "100") then -- offline or idle
twi_phase_gen <= "0001"; -- make sure to start with a new phase, 0,1,2,3 stepping
twi_phase_gen <= "0001"; -- make sure to start with a new phase, bit 0,1,2,3 stepping
elsif (twi_clk = '1') and (twi_clk_halt = '0') then -- enabled and no clock stretching detected
twi_phase_gen <= twi_phase_gen(2 downto 0) & twi_phase_gen(3); -- rotate left
end if;
@ -203,7 +203,7 @@ begin
case arbiter is
when "100" => -- IDLE: waiting for requests, bus might be still claimed by this controller if no STOP condition was generated
twi_bitcnt <= (others => '0');
bitcnt <= (others => '0');
if (wr_en = '1') then
if (addr = twi_ctrl_addr_c) then
if (data_i(ctrl_twi_start_c) = '1') then -- issue START condition
@ -214,7 +214,7 @@ begin
elsif (addr = twi_rtx_addr_c) then -- start a data transmission
-- one bit extra for ack, issued by controller if ctrl_twi_mack_c is set,
-- sampled from peripheral if ctrl_twi_mack_c is cleared
twi_rtx_sreg <= data_i(7 downto 0) & (not ctrl(ctrl_twi_mack_c));
rtx_sreg <= data_i(7 downto 0) & (not ctrl(ctrl_twi_mack_c));
arbiter(1 downto 0) <= "11";
end if;
end if;
@ -225,7 +225,7 @@ begin
elsif (twi_clk_phase(1) = '1') then
twi_sda_o <= '0';
end if;
--
if (twi_clk_phase(0) = '1') then
twi_scl_o <= '1';
elsif (twi_clk_phase(3) = '1') then
@ -240,7 +240,7 @@ begin
twi_sda_o <= '1';
arbiter(1 downto 0) <= "00"; -- go back to IDLE
end if;
--
if (twi_clk_phase(0) = '1') then
twi_scl_o <= '0';
elsif (twi_clk_phase(1) = '1') then
@ -249,17 +249,17 @@ begin
when "111" => -- TRANSMISSION: transmission in progress
if (twi_clk_phase(0) = '1') then
twi_bitcnt <= std_ulogic_vector(unsigned(twi_bitcnt) + 1);
twi_scl_o <= '0';
twi_sda_o <= twi_rtx_sreg(8); -- MSB first
bitcnt <= std_ulogic_vector(unsigned(bitcnt) + 1);
twi_scl_o <= '0';
twi_sda_o <= rtx_sreg(8); -- MSB first
elsif (twi_clk_phase(1) = '1') then -- first half + second half of valid data strobe
twi_scl_o <= '1';
twi_scl_o <= '1';
elsif (twi_clk_phase(3) = '1') then
twi_rtx_sreg <= twi_rtx_sreg(7 downto 0) & twi_sda_i_ff1; -- sample and shift left
twi_scl_o <= '0';
rtx_sreg <= rtx_sreg(7 downto 0) & twi_sda_i_ff1; -- sample and shift left
twi_scl_o <= '0';
end if;
if (twi_bitcnt = "1010") then -- 8 data bits + 1 bit for ACK + 1 tick delay
--
if (bitcnt = "1010") then -- 8 data bits + 1 bit for ACK + 1 tick delay
arbiter(1 downto 0) <= "00"; -- go back to IDLE
end if;

View file

@ -49,11 +49,11 @@ entity neorv32_ProcessorTop_stdlogic is
ON_CHIP_DEBUGGER_EN : boolean := false; -- implement on-chip debugger
-- RISC-V CPU Extensions --
CPU_EXTENSION_RISCV_A : boolean := false; -- implement atomic extension?
CPU_EXTENSION_RISCV_B : boolean := false; -- implement bit-manipulation extension?
CPU_EXTENSION_RISCV_C : boolean := false; -- implement compressed extension?
CPU_EXTENSION_RISCV_E : boolean := false; -- implement embedded RF extension?
CPU_EXTENSION_RISCV_M : boolean := false; -- implement muld/div extension?
CPU_EXTENSION_RISCV_U : boolean := false; -- implement user mode extension?
CPU_EXTENSION_RISCV_Zbb : boolean := false; -- implement basic bit-manipulation sub-extension?
CPU_EXTENSION_RISCV_Zfinx : boolean := false; -- implement 32-bit floating-point extension (using INT reg!)
CPU_EXTENSION_RISCV_Zicsr : boolean := true; -- implement CSR system?
CPU_EXTENSION_RISCV_Zifencei : boolean := false; -- implement instruction stream sync.?
@ -272,11 +272,11 @@ begin
ON_CHIP_DEBUGGER_EN => ON_CHIP_DEBUGGER_EN, -- implement on-chip debugger
-- RISC-V CPU Extensions --
CPU_EXTENSION_RISCV_A => CPU_EXTENSION_RISCV_A, -- implement atomic extension?
CPU_EXTENSION_RISCV_B => CPU_EXTENSION_RISCV_B, -- implement bit-manipulation extension?
CPU_EXTENSION_RISCV_C => CPU_EXTENSION_RISCV_C, -- implement compressed extension?
CPU_EXTENSION_RISCV_E => CPU_EXTENSION_RISCV_E, -- implement embedded RF extension?
CPU_EXTENSION_RISCV_M => CPU_EXTENSION_RISCV_M, -- implement muld/div extension?
CPU_EXTENSION_RISCV_U => CPU_EXTENSION_RISCV_U, -- implement user mode extension?
CPU_EXTENSION_RISCV_Zbb => CPU_EXTENSION_RISCV_Zbb, -- implement basic bit-manipulation sub-extension?
CPU_EXTENSION_RISCV_Zfinx => CPU_EXTENSION_RISCV_Zfinx, -- implement 32-bit floating-point extension (using INT reg!)
CPU_EXTENSION_RISCV_Zicsr => CPU_EXTENSION_RISCV_Zicsr, -- implement CSR system?
CPU_EXTENSION_RISCV_Zifencei => CPU_EXTENSION_RISCV_Zifencei, -- implement instruction stream sync.?

View file

@ -54,11 +54,11 @@ entity neorv32_top_avalonmm is
-- RISC-V CPU Extensions --
CPU_EXTENSION_RISCV_A : boolean := false; -- implement atomic extension?
CPU_EXTENSION_RISCV_B : boolean := false; -- implement bit-manipulation extension?
CPU_EXTENSION_RISCV_C : boolean := false; -- implement compressed extension?
CPU_EXTENSION_RISCV_E : boolean := false; -- implement embedded RF extension?
CPU_EXTENSION_RISCV_M : boolean := false; -- implement mul/div extension?
CPU_EXTENSION_RISCV_U : boolean := false; -- implement user mode extension?
CPU_EXTENSION_RISCV_Zbb : boolean := false; -- implement basic bit-manipulation sub-extension?
CPU_EXTENSION_RISCV_Zfinx : boolean := false; -- implement 32-bit floating-point extension (using INT regs!)
CPU_EXTENSION_RISCV_Zicsr : boolean := true; -- implement CSR system?
CPU_EXTENSION_RISCV_Zifencei : boolean := false; -- implement instruction stream sync.?
@ -238,11 +238,11 @@ begin
-- RISC-V CPU Extensions --
CPU_EXTENSION_RISCV_A => CPU_EXTENSION_RISCV_A,
CPU_EXTENSION_RISCV_B => CPU_EXTENSION_RISCV_B,
CPU_EXTENSION_RISCV_C => CPU_EXTENSION_RISCV_C,
CPU_EXTENSION_RISCV_E => CPU_EXTENSION_RISCV_E,
CPU_EXTENSION_RISCV_M => CPU_EXTENSION_RISCV_M,
CPU_EXTENSION_RISCV_U => CPU_EXTENSION_RISCV_U,
CPU_EXTENSION_RISCV_Zbb => CPU_EXTENSION_RISCV_Zbb,
CPU_EXTENSION_RISCV_Zfinx => CPU_EXTENSION_RISCV_Zfinx,
CPU_EXTENSION_RISCV_Zicsr => CPU_EXTENSION_RISCV_Zicsr,
CPU_EXTENSION_RISCV_Zifencei => CPU_EXTENSION_RISCV_Zifencei,

View file

@ -55,11 +55,11 @@ entity neorv32_SystemTop_axi4lite is
ON_CHIP_DEBUGGER_EN : boolean := false; -- implement on-chip debugger
-- RISC-V CPU Extensions --
CPU_EXTENSION_RISCV_A : boolean := false; -- implement atomic extension?
CPU_EXTENSION_RISCV_B : boolean := false; -- implement bit-manipulation extension?
CPU_EXTENSION_RISCV_C : boolean := false; -- implement compressed extension?
CPU_EXTENSION_RISCV_E : boolean := false; -- implement embedded RF extension?
CPU_EXTENSION_RISCV_M : boolean := false; -- implement muld/div extension?
CPU_EXTENSION_RISCV_U : boolean := false; -- implement user mode extension?
CPU_EXTENSION_RISCV_Zbb : boolean := false; -- implement basic bit-manipulation sub-extension?
CPU_EXTENSION_RISCV_Zfinx : boolean := false; -- implement 32-bit floating-point extension (using INT reg!)
CPU_EXTENSION_RISCV_Zicsr : boolean := true; -- implement CSR system?
CPU_EXTENSION_RISCV_Zifencei : boolean := false; -- implement instruction stream sync.?
@ -279,11 +279,11 @@ begin
ON_CHIP_DEBUGGER_EN => ON_CHIP_DEBUGGER_EN, -- implement on-chip debugger
-- RISC-V CPU Extensions --
CPU_EXTENSION_RISCV_A => CPU_EXTENSION_RISCV_A, -- implement atomic extension?
CPU_EXTENSION_RISCV_B => CPU_EXTENSION_RISCV_B, -- implement bit-manipulation extension?
CPU_EXTENSION_RISCV_C => CPU_EXTENSION_RISCV_C, -- implement compressed extension?
CPU_EXTENSION_RISCV_E => CPU_EXTENSION_RISCV_E, -- implement embedded RF extension?
CPU_EXTENSION_RISCV_M => CPU_EXTENSION_RISCV_M, -- implement muld/div extension?
CPU_EXTENSION_RISCV_U => CPU_EXTENSION_RISCV_U, -- implement user mode extension?
CPU_EXTENSION_RISCV_Zbb => CPU_EXTENSION_RISCV_Zbb, -- implement basic bit-manipulation sub-extension?
CPU_EXTENSION_RISCV_Zfinx => CPU_EXTENSION_RISCV_Zfinx, -- implement 32-bit floating-point extension (using INT reg!)
CPU_EXTENSION_RISCV_Zicsr => CPU_EXTENSION_RISCV_Zicsr, -- implement CSR system?
CPU_EXTENSION_RISCV_Zifencei => CPU_EXTENSION_RISCV_Zifencei, -- implement instruction stream sync.?

View file

@ -76,11 +76,11 @@ architecture neorv32_test_setup_avalonmm_rtl of neorv32_test_setup_avalonmm is
-- RISC-V CPU Extensions --
CPU_EXTENSION_RISCV_A : boolean := false; -- implement atomic extension?
CPU_EXTENSION_RISCV_B : boolean := false; -- implement bit-manipulation extension?
CPU_EXTENSION_RISCV_C : boolean := false; -- implement compressed extension?
CPU_EXTENSION_RISCV_E : boolean := false; -- implement embedded RF extension?
CPU_EXTENSION_RISCV_M : boolean := false; -- implement mul/div extension?
CPU_EXTENSION_RISCV_U : boolean := false; -- implement user mode extension?
CPU_EXTENSION_RISCV_Zbb : boolean := false; -- implement basic bit-manipulation sub-extension?
CPU_EXTENSION_RISCV_Zfinx : boolean := false; -- implement 32-bit floating-point extension (using INT regs!)
CPU_EXTENSION_RISCV_Zicsr : boolean := true; -- implement CSR system?
CPU_EXTENSION_RISCV_Zifencei : boolean := false; -- implement instruction stream sync.?

View file

@ -284,11 +284,11 @@ begin
ON_CHIP_DEBUGGER_EN => true, -- implement on-chip debugger
-- RISC-V CPU Extensions --
CPU_EXTENSION_RISCV_A => true, -- implement atomic extension?
CPU_EXTENSION_RISCV_B => true, -- implement bit-manipulation extension?
CPU_EXTENSION_RISCV_C => true, -- implement compressed extension?
CPU_EXTENSION_RISCV_E => false, -- implement embedded RF extension?
CPU_EXTENSION_RISCV_M => true, -- implement muld/div extension?
CPU_EXTENSION_RISCV_U => true, -- implement user mode extension?
CPU_EXTENSION_RISCV_Zbb => true, -- implement basic bit-manipulation sub-extension?
CPU_EXTENSION_RISCV_Zfinx => true, -- implement 32-bit floating-point extension (using INT reg!)
CPU_EXTENSION_RISCV_Zicsr => true, -- implement CSR system?
CPU_EXTENSION_RISCV_Zifencei => true, -- implement instruction stream sync.?

View file

@ -49,11 +49,11 @@ use std.textio.all;
entity neorv32_tb_simple is
generic (
CPU_EXTENSION_RISCV_A : boolean := true;
CPU_EXTENSION_RISCV_B : boolean := true;
CPU_EXTENSION_RISCV_C : boolean := true;
CPU_EXTENSION_RISCV_E : boolean := false;
CPU_EXTENSION_RISCV_M : boolean := true;
CPU_EXTENSION_RISCV_U : boolean := true;
CPU_EXTENSION_RISCV_Zbb : boolean := true;
CPU_EXTENSION_RISCV_Zicsr : boolean := true;
CPU_EXTENSION_RISCV_Zifencei : boolean := true;
EXT_IMEM_C : boolean := false; -- false: use and boot from proc-internal IMEM, true: use and boot from external (initialized) simulated IMEM (ext. mem A)
@ -176,11 +176,11 @@ begin
ON_CHIP_DEBUGGER_EN => true, -- implement on-chip debugger
-- RISC-V CPU Extensions --
CPU_EXTENSION_RISCV_A => CPU_EXTENSION_RISCV_A, -- implement atomic extension?
CPU_EXTENSION_RISCV_B => CPU_EXTENSION_RISCV_B, -- implement bit-manipulation extension?
CPU_EXTENSION_RISCV_C => CPU_EXTENSION_RISCV_C, -- implement compressed extension?
CPU_EXTENSION_RISCV_E => CPU_EXTENSION_RISCV_E, -- implement embedded RF extension?
CPU_EXTENSION_RISCV_M => CPU_EXTENSION_RISCV_M, -- implement muld/div extension?
CPU_EXTENSION_RISCV_U => CPU_EXTENSION_RISCV_U, -- implement user mode extension?
CPU_EXTENSION_RISCV_Zbb => CPU_EXTENSION_RISCV_Zbb,-- implement basic bit-manipulation sub-extension?
CPU_EXTENSION_RISCV_Zfinx => true, -- implement 32-bit floating-point extension (using INT reg!)
CPU_EXTENSION_RISCV_Zicsr => CPU_EXTENSION_RISCV_Zicsr, -- implement CSR system?
CPU_EXTENSION_RISCV_Zifencei => CPU_EXTENSION_RISCV_Zifencei, -- implement instruction stream sync.?

View file

@ -1,12 +1,12 @@
# NEORV32 Bit-Manipulation `B` Extension (`Zbb` sub-extension)
# NEORV32 Bit-Manipulation `B` Extension
:warning: The RISC-V bit-manipulation extension is frozen but not yet officially ratified.
:warning: The NEORV32 bit manipulation extensions only supports the `Zbb` sub-extension
:warning: The NEORV32 bit manipulation extensions `B` only supports the `Zbb` and `Zba` sub-extension
(basic bit-manipulation operation) yet.
The provided test program `main.c` verifies all currently implemented instruction by checking the results against a pure-software emulation model.
The emulation functions as well as the available **intrinsics** for the `Zbb` extension are located in `neorv32_b_extension_intrinsics.h`.
The emulation functions as well as the available **intrinsics** for the sub-extension are located in `neorv32_b_extension_intrinsics.h`.
:information_source: More information regarding the RISC-V bit manipulation extension can be found in the officail GitHub repo:
[github.com/riscv/riscv-bitmanip](https://github.com/riscv/riscv-bitmanip).

View file

@ -1,5 +1,5 @@
// #################################################################################################
// # << NEORV32 - RISC-V Bit-Manipulation 'Zbb' Extension Test Program >> #
// # << NEORV32 - RISC-V Bit-Manipulation 'B' Extension Test Program >> #
// # ********************************************************************************************* #
// # BSD 3-Clause License #
// # #
@ -36,7 +36,7 @@
/**********************************************************************//**
* @file bitmanip_test/main.c
* @author Stephan Nolting
* @brief Test program for the NEORV32 'Zbb' extension using pseudo-random
* @brief Test program for the NEORV32 'B` extension using pseudo-random
* data as input; compares results from hardware against pure-sw reference functions.
**************************************************************************/
@ -64,7 +64,7 @@ void print_report(int num_err, int num_tests);
* Main function; test all available operations of the NEORV32 'Zbb' extensions
* using bit manipulation intrinsics and software-only reference functions (emulation).
*
* @note This program requires the Zbb CPU extension.
* @note This program requires the bit-manipulation CPU extension.
*
* @return Irrelevant.
**************************************************************************/
@ -91,18 +91,22 @@ int main() {
#endif
// intro
neorv32_uart0_printf("NEORV32 'Zbb' Bit-Manipulation Extension Test\n\n");
neorv32_uart0_printf("NEORV32 Bit-Manipulation Extension Test (Zba, Zbb)\n\n");
// check available hardware extensions and compare with compiler flags
neorv32_rte_check_isa(0); // silent = 0 -> show message if isa mismatch
// check if Zbb extension is implemented at all
if ((NEORV32_SYSINFO.CPU & (1<<SYSINFO_CPU_ZBB)) == 0) {
neorv32_uart0_print("Error! <Zbb> extension not synthesized!\n");
if ((neorv32_cpu_csr_read(CSR_MISA) & (1<<CSR_MISA_B)) == 0) {
neorv32_uart0_print("Error! <B> extension not synthesized!\n");
return 1;
}
neorv32_uart0_printf("Starting Zbb bit-manipulation extension tests (%i test cases per instruction)...\n", num_tests);
neorv32_uart0_printf("Starting bit-manipulation extension tests (%i test cases per instruction)...\n\n", num_tests);
neorv32_uart0_printf("-----------------------------------------\n");
neorv32_uart0_printf("Zbb - Basic bit-manipulation instructions\n");
neorv32_uart0_printf("-----------------------------------------\n");
// ANDN
neorv32_uart0_printf("\nANDN:\n");
@ -326,6 +330,48 @@ int main() {
print_report(err_cnt, num_tests);
neorv32_uart0_printf("\n\n");
neorv32_uart0_printf("-----------------------------------------\n");
neorv32_uart0_printf("Zba - Address generation instructions\n");
neorv32_uart0_printf("-----------------------------------------\n");
// SH1ADD
neorv32_uart0_printf("\nSH1ADD:\n");
err_cnt = 0;
for (i=0;i<num_tests; i++) {
opa = xorshift32();
opb = xorshift32();
res_sw = riscv_emulate_sh1add(opa, opb);
res_hw = riscv_intrinsic_sh1add(opa, opb);
err_cnt += check_result(i, opa, opb, res_sw, res_hw);
}
print_report(err_cnt, num_tests);
// SH2ADD
neorv32_uart0_printf("\nSH2ADD:\n");
err_cnt = 0;
for (i=0;i<num_tests; i++) {
opa = xorshift32();
opb = xorshift32();
res_sw = riscv_emulate_sh2add(opa, opb);
res_hw = riscv_intrinsic_sh2add(opa, opb);
err_cnt += check_result(i, opa, opb, res_sw, res_hw);
}
print_report(err_cnt, num_tests);
// SH2ADD
neorv32_uart0_printf("\nSH3ADD:\n");
err_cnt = 0;
for (i=0;i<num_tests; i++) {
opa = xorshift32();
res_sw = riscv_emulate_sh3add(opa, opb);
res_hw = riscv_intrinsic_sh3add(opa, opb);
err_cnt += check_result(i, opa, opb, res_sw, res_hw);
}
print_report(err_cnt, num_tests);
neorv32_uart0_printf("\nBit manipulation extension tests done.\n");
return 0;

View file

@ -1,8 +1,8 @@
// #################################################################################################
// # << NEORV32 - Intrinsics + Emulation Functions for the B CPU extensions >> #
// # << NEORV32 - Intrinsics + Emulation Functions for the CPU B extension >> #
// # ********************************************************************************************* #
// # The intrinsics provided by this library allow to use the hardware bit manipulation unit of #
// # the RISC-V B CPU extension without the need for B support by the compiler. #
// # the RISC-V B CPU extension without the need for support by the compiler. #
// # ********************************************************************************************* #
// # BSD 3-Clause License #
// # #
@ -39,10 +39,10 @@
/**********************************************************************//**
* @file bitmanip_test/neorv32_b_extension_intrinsics.h
* @author Stephan Nolting
* @brief "Intrinsic" library for the NEORV32 bit manipulation Zbb extension.
* @brief "Intrinsic" library for the NEORV32 bit manipulation B extension.
* Also provides emulation functions for all intrinsics (functionality re-built in pure software).
*
* @warning This library is just a temporary fall-back until the Zbb extensions are supported by the upstream RISC-V GCC port.
* @warning This library is just a temporary fall-back until the B extension is supported by the upstream RISC-V GCC port.
**************************************************************************/
#ifndef neorv32_b_extension_intrinsics_h
@ -54,9 +54,9 @@
// ################################################################################################
// ---------------------------------------------
// ================================================================================================
// Zbb - Base instructions
// ---------------------------------------------
// ================================================================================================
/**********************************************************************//**
* Intrinsic: Bit manipulation CLZ (count leading zeros) [B.Zbb]
@ -455,14 +455,87 @@ inline uint32_t __attribute__ ((always_inline)) riscv_intrinsic_rev8(uint32_t rs
}
// ================================================================================================
// Zbb - Base instructions
// ================================================================================================
/**********************************************************************//**
* Intrinsic: Address generation instructions SH1ADD (add with logical-1-shift) [B.Zba]
*
* @param[in] rs1 Source operand 1 (a0).
* @param[in] rs2 Source operand 2 (a0).
* @return Operand 2 + (Operand 1 << 1)
**************************************************************************/
inline uint32_t __attribute__ ((always_inline)) riscv_intrinsic_sh1add(uint32_t rs1, uint32_t rs2) {
register uint32_t result __asm__ ("a0");
register uint32_t tmp_a __asm__ ("a0") = rs1;
register uint32_t tmp_b __asm__ ("a1") = rs2;
// dummy instruction to prevent GCC "constprop" optimization
asm volatile ("" : [output] "=r" (result) : [input_i] "r" (tmp_a), [input_j] "r" (tmp_b));
// sh1add a0, a0, a1
CUSTOM_INSTR_R2_TYPE(0b0010000, a1, a0, 0b010, a0, 0b0110011);
return result;
}
/**********************************************************************//**
* Intrinsic: Address generation instructions SH2ADD (add with logical-2-shift) [B.Zba]
*
* @param[in] rs1 Source operand 1 (a0).
* @param[in] rs2 Source operand 2 (a0).
* @return Operand 2 + (Operand 1 << 2)
**************************************************************************/
inline uint32_t __attribute__ ((always_inline)) riscv_intrinsic_sh2add(uint32_t rs1, uint32_t rs2) {
register uint32_t result __asm__ ("a0");
register uint32_t tmp_a __asm__ ("a0") = rs1;
register uint32_t tmp_b __asm__ ("a1") = rs2;
// dummy instruction to prevent GCC "constprop" optimization
asm volatile ("" : [output] "=r" (result) : [input_i] "r" (tmp_a), [input_j] "r" (tmp_b));
// sh2add a0, a0, a1
CUSTOM_INSTR_R2_TYPE(0b0010000, a1, a0, 0b100, a0, 0b0110011);
return result;
}
/**********************************************************************//**
* Intrinsic: Address generation instructions SH1ADD (add with logical-3-shift) [B.Zba]
*
* @param[in] rs1 Source operand 1 (a0).
* @param[in] rs2 Source operand 2 (a0).
* @return Operand 2 + (Operand 1 << 3)
**************************************************************************/
inline uint32_t __attribute__ ((always_inline)) riscv_intrinsic_sh3add(uint32_t rs1, uint32_t rs2) {
register uint32_t result __asm__ ("a0");
register uint32_t tmp_a __asm__ ("a0") = rs1;
register uint32_t tmp_b __asm__ ("a1") = rs2;
// dummy instruction to prevent GCC "constprop" optimization
asm volatile ("" : [output] "=r" (result) : [input_i] "r" (tmp_a), [input_j] "r" (tmp_b));
// sh3add a0, a0, a1
CUSTOM_INSTR_R2_TYPE(0b0010000, a1, a0, 0b110, a0, 0b0110011);
return result;
}
// ################################################################################################
// Emulation functions
// ################################################################################################
// ---------------------------------------------
// ================================================================================================
// Zbb - Base instructions
// ---------------------------------------------
// ================================================================================================
/**********************************************************************//**
@ -783,5 +856,48 @@ uint32_t riscv_emulate_orcb(uint32_t rs1) {
}
// ================================================================================================
// Zba - Address generation instructions
// ================================================================================================
/**********************************************************************//**
* Intrinsic: Address generation instructions SH1ADD (add with logical-1-shift) [emulation]
*
* @param[in] rs1 Source operand 1 (a0).
* @param[in] rs2 Source operand 1 (a0).
* @return Operand 2 + (Operand 1 << 1)
**************************************************************************/
uint32_t riscv_emulate_sh1add(uint32_t rs1, uint32_t rs2) {
return rs2 + (rs1 << 1);
}
/**********************************************************************//**
* Intrinsic: Address generation instructions SH2ADD (add with logical-2-shift) [emulation]
*
* @param[in] rs1 Source operand 1 (a0).
* @param[in] rs2 Source operand 1 (a0).
* @return Operand 2 + (Operand 1 << 2)
**************************************************************************/
uint32_t riscv_emulate_sh2add(uint32_t rs1, uint32_t rs2) {
return rs2 + (rs1 << 2);
}
/**********************************************************************//**
* Intrinsic: Address generation instructions SH3ADD (add with logical-3-shift) [emulation]
*
* @param[in] rs1 Source operand 1 (a0).
* @param[in] rs2 Source operand 1 (a0).
* @return Operand 2 + (Operand 1 << 3)
**************************************************************************/
uint32_t riscv_emulate_sh3add(uint32_t rs1, uint32_t rs2) {
return rs2 + (rs1 << 3);
}
#endif // neorv32_b_extension_intrinsics_h

View file

@ -1139,7 +1139,6 @@ enum NEORV32_SYSINFO_CPU_enum {
SYSINFO_CPU_ZICSR = 0, /**< SYSINFO_CPU (0): Zicsr extension (I sub-extension) available when set (r/-) */
SYSINFO_CPU_ZIFENCEI = 1, /**< SYSINFO_CPU (1): Zifencei extension (I sub-extension) available when set (r/-) */
SYSINFO_CPU_ZMMUL = 2, /**< SYSINFO_CPU (2): Zmmul extension (M sub-extension) available when set (r/-) */
SYSINFO_CPU_ZBB = 3, /**< SYSINFO_CPU (3): Zbb extension (B sub-extension) available when set (r/-) */
SYSINFO_CPU_ZFINX = 5, /**< SYSINFO_CPU (5): Zfinx extension (F sub-/alternative-extension) available when set (r/-) */
SYSINFO_CPU_ZXSCNT = 6, /**< SYSINFO_CPU (6): Custom extension - Small CPU counters: "cycle" & "instret" CSRs have less than 64-bit when set (r/-) */

View file

@ -330,9 +330,6 @@ void neorv32_rte_print_hw_config(void) {
if (tmp & (1<<SYSINFO_CPU_ZMMUL)) {
neorv32_uart0_printf("Zmmul ");
}
if (tmp & (1<<SYSINFO_CPU_ZBB)) {
neorv32_uart0_printf("Zbb ");
}
if (tmp & (1<<SYSINFO_CPU_ZFINX)) {
neorv32_uart0_printf("Zfinx ");