Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Rework C decompressor #296

Merged
merged 7 commits into from
Apr 8, 2022
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,7 @@ The version number is globally defined by the `hw_version_c` constant in the mai

| Date (*dd.mm.yyyy*) | Version | Comment |
|:----------:|:-------:|:--------|
| 08.04.2022 | 1.6.9.10 | rework compressed instruction (`C` ISA extension) de-compressor: :lock: closed further illegal compressed instruction holes; code clean-ups; `mtval` CSR now shows the decompressed 32-bit instruction when executing an illegal compressed instruction; minor RTL code cleanups (removing legacy stuff); [PR #296](https://github.com/stnolting/neorv32/pull/296) |
| 07.04.2022 | 1.6.9.9 | AND-gate CSR read address: reduces **CPU switching activity** (= dynamic power consumption) and even reduces area costs; [PR #295](https://github.com/stnolting/neorv32/pull/295) |
| 06.04.2022 | 1.6.9.8 | :bug: fixed instruction decoding collision in CPU `B` extension; :lock: closed further illegal instruction encoding holes; optimized illegal instruction detection logic; [PR #294](https://github.com/stnolting/neorv32/pull/294) |
| 04.04.2022 | 1.6.9.7 | **major CPU logic optimization**: reduced area costs and shortened critical path (higher f_max!); :bug: fixed rare bug in RTE core (if C-extension is not implemented); :lock: closed further illegal instruction encoding holes; [PR #293](https://github.com/stnolting/neorv32/pull/293) |
Expand Down
7 changes: 6 additions & 1 deletion docs/datasheet/cpu_csr.adoc
Original file line number Diff line number Diff line change
Expand Up @@ -423,7 +423,7 @@ interrupt) this register provides the address of the next not-yet-executed instr
| 0x343 | **Machine bad address or instruction** | `mtval`
3+| Reset value: _UNDEFINED_
3+| The `mtval` CSR is compatible to the RISC-V specifications. When a trap is triggered, the CSR shows either
the faulting address (for misaligned/faulting load/store/fetch) or the faulting instruction word itself (for illegal
the faulting address (for misaligned/faulting load/store/fetch) or the faulting (decompressed) instruction word itself (for illegal
instructions). For all other exceptions (including interrupts) the CSR is set to zero.
|=======================

Expand All @@ -441,6 +441,11 @@ instructions). For all other exceptions (including interrupts) the CSR is set to
[IMPORTANT]
The NEORV32 `mtval` CSR is read-only. However, a write access will _NOT_ raise an illegal instruction exception.

[NOTE]
In case an invalid compressed instruction raised an illegal instruction exception, `mtval` will show the
according de-compressed instruction word. To get the "real" 16-bit instruction that caused the exception
perform a memory load using the address stored in <<_mepc>>.

:sectnums!:
===== **`mip`**

Expand Down
20 changes: 7 additions & 13 deletions rtl/core/neorv32_cpu_control.vhd
Original file line number Diff line number Diff line change
Expand Up @@ -755,9 +755,6 @@ begin
-- memory access size / sign --
ctrl_o(ctrl_bus_unsigned_c) <= execute_engine.i_reg(instr_funct3_msb_c); -- unsigned LOAD (LBU, LHU)
ctrl_o(ctrl_bus_size_msb_c downto ctrl_bus_size_lsb_c) <= execute_engine.i_reg(instr_funct3_lsb_c+1 downto instr_funct3_lsb_c); -- mem transfer size
-- alu.shifter --
ctrl_o(ctrl_alu_shift_dir_c) <= execute_engine.i_reg(instr_funct3_msb_c); -- shift direction (left/right)
ctrl_o(ctrl_alu_shift_ar_c) <= execute_engine.i_reg(30); -- is arithmetic shift
-- instruction's function blocks (for co-processors) --
ctrl_o(ctrl_ir_opcode7_6_c downto ctrl_ir_opcode7_0_c) <= execute_engine.i_reg(instr_opcode_msb_c downto instr_opcode_lsb_c);
ctrl_o(ctrl_ir_funct12_11_c downto ctrl_ir_funct12_0_c) <= execute_engine.i_reg(instr_funct12_msb_c downto instr_funct12_lsb_c);
Expand Down Expand Up @@ -881,7 +878,7 @@ begin
end process decode_helper;

-- CSR access address --
csr.addr <= execute_engine.i_reg(instr_csr_id_msb_c downto instr_csr_id_lsb_c);
csr.addr <= execute_engine.i_reg(instr_imm12_msb_c downto instr_imm12_lsb_c);


-- Execute Engine FSM Comb ----------------------------------------------------------------
Expand Down Expand Up @@ -939,22 +936,19 @@ begin

when DISPATCH => -- Get new command from instruction issue engine
-- ------------------------------------------------------------
-- PC update --
-- PC & IR update --
execute_engine.pc_mux_sel <= '0'; -- linear next PC
-- IR update --
execute_engine.is_ci_nxt <= issue_engine.data(32); -- flag to indicate a de-compressed instruction
execute_engine.i_reg_nxt <= issue_engine.data(31 downto 0);
execute_engine.i_reg_nxt <= issue_engine.data(31 downto 0);
execute_engine.is_ci_nxt <= issue_engine.data(32); -- this is a de-compressed instruction
execute_engine.is_ici_nxt <= issue_engine.data(35); -- illegal compressed instruction
--
if (issue_engine.valid(0) = '1') or (issue_engine.valid(1) = '1') then -- instruction available?
-- PC update --
execute_engine.branched_nxt <= '0';
execute_engine.pc_we <= not execute_engine.branched; -- update PC with linear next_pc if there was no actual branch
-- IR update - exceptions --
if (CPU_EXTENSION_RISCV_C = false) then
trap_ctrl.instr_ma <= issue_engine.data(33); -- misaligned instruction fetch address, if C disabled
end if;
trap_ctrl.instr_be <= issue_engine.data(34); -- bus access fault during instruction fetch
execute_engine.is_ici_nxt <= issue_engine.data(35); -- invalid decompressed instruction
trap_ctrl.instr_ma <= issue_engine.data(33) and (not bool_to_ulogic_f(CPU_EXTENSION_RISCV_C)); -- misaligned instruction fetch (if C disabled)
trap_ctrl.instr_be <= issue_engine.data(34); -- bus access fault during instruction fetch
-- any reason to go to trap state? --
if (execute_engine.sleep = '1') or -- enter sleep state
(trap_ctrl.exc_fire = '1') or -- exception during LAST instruction (e.g. illegal instruction)
Expand Down
10 changes: 5 additions & 5 deletions rtl/core/neorv32_cpu_cp_shifter.vhd
Original file line number Diff line number Diff line change
Expand Up @@ -106,10 +106,10 @@ begin
shifter.cnt <= shamt_i; -- shift amount
elsif (or_reduce_f(shifter.cnt) = '1') then -- running shift (cnt != 0)
shifter.cnt <= std_ulogic_vector(unsigned(shifter.cnt) - 1);
if (ctrl_i(ctrl_alu_shift_dir_c) = '0') then -- SLL: shift left logical
if (ctrl_i(ctrl_ir_funct3_2_c) = '0') then -- SLL: shift left logical
shifter.sreg <= shifter.sreg(shifter.sreg'left-1 downto 0) & '0';
else -- SRL: shift right logical / SRA: shift right arithmetical
shifter.sreg <= (shifter.sreg(shifter.sreg'left) and ctrl_i(ctrl_alu_shift_ar_c)) & shifter.sreg(shifter.sreg'left downto 1);
shifter.sreg <= (shifter.sreg(shifter.sreg'left) and ctrl_i(ctrl_ir_funct12_10_c)) & shifter.sreg(shifter.sreg'left downto 1);
end if;
end if;
end if;
Expand All @@ -132,7 +132,7 @@ begin
shifter_unit_async: process(rs1_i, shamt_i, ctrl_i, bs_level)
begin
-- input level: convert left shifts to right shifts --
if (ctrl_i(ctrl_alu_shift_dir_c) = '0') then -- is left shift?
if (ctrl_i(ctrl_ir_funct3_2_c) = '0') then -- is left shift?
bs_level(index_size_f(data_width_c)) <= bit_rev_f(rs1_i); -- reverse bit order of input operand
else
bs_level(index_size_f(data_width_c)) <= rs1_i;
Expand All @@ -141,15 +141,15 @@ begin
-- shifter array --
for i in index_size_f(data_width_c)-1 downto 0 loop
if (shamt_i(i) = '1') then
bs_level(i)(data_width_c-1 downto data_width_c-(2**i)) <= (others => (bs_level(i+1)(data_width_c-1) and ctrl_i(ctrl_alu_shift_ar_c)));
bs_level(i)(data_width_c-1 downto data_width_c-(2**i)) <= (others => (bs_level(i+1)(data_width_c-1) and ctrl_i(ctrl_ir_funct12_10_c)));
bs_level(i)((data_width_c-(2**i))-1 downto 0) <= bs_level(i+1)(data_width_c-1 downto 2**i);
else
bs_level(i) <= bs_level(i+1);
end if;
end loop;

-- re-convert original left shifts --
if (ctrl_i(ctrl_alu_shift_dir_c) = '0') then
if (ctrl_i(ctrl_ir_funct3_2_c) = '0') then
bs_result <= bit_rev_f(bs_level(0));
else
bs_result <= bs_level(0);
Expand Down
Loading