Skip to content

Commit

Permalink
Rework C decompressor (#296)
Browse files Browse the repository at this point in the history
* minor cleanup

* rework C decompressor

* illegal c.instructions do not fall-back to all-zero instruction words
* closed further C illegal instruction holes
* code cleanups

* mtval now also provides decompressed instruction

* add v1.6.9.10

* code cleanup

* remove legacy rtl code

-> cleanup

* Update CHANGELOG.md
  • Loading branch information
stnolting authored Apr 8, 2022
1 parent bd379f0 commit b5bff46
Show file tree
Hide file tree
Showing 7 changed files with 135 additions and 173 deletions.
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

0 comments on commit b5bff46

Please sign in to comment.