diff --git a/CHANGELOG.md b/CHANGELOG.md index 111931e58..1d5630ade 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -32,6 +32,7 @@ mimpid = 0x01040312 -> Version 01.04.03.12 -> v1.4.3.12 | Date (*dd.mm.yyyy*) | Version | Comment | |:-------------------:|:-------:|:--------| +| 29.07.2023 | 1.8.7.4 | RTL cleanup and optimizations (less synthesis warnings, less resource requirements); [#660](https://github.com/stnolting/neorv32/pull/660) | | 28.07.2023 | 1.8.7.3 | :warning: reworked **SYSINFO** module; clean-up address space layout; clean-up assertion notes; [#659](https://github.com/stnolting/neorv32/pull/659) | | 27.07.2023 | 1.8.7.2 | :bug: make sure that IMEM/DMEM size is always a power of two; [#658](https://github.com/stnolting/neorv32/pull/658) | | 27.07.2023 | 1.8.7.1 | :warning: remove `CUSTOM_ID` generic; cleanup and re-layout `NEORV32_SYSINFO.SOC` bits; (:bug:) fix gateway's generics (`positive` -> `natural` as these generics are allowed to be zero); [#657](https://github.com/stnolting/neorv32/pull/657) | diff --git a/docs/datasheet/cpu.adoc b/docs/datasheet/cpu.adoc index 7f0fe3627..df20769ea 100644 --- a/docs/datasheet/cpu.adoc +++ b/docs/datasheet/cpu.adoc @@ -145,7 +145,8 @@ The control unit is split into a "front-end" and a "back-end". The front-end is responsible for fetching instructions in chunks of 32-bits. This can be a single aligned 32-bit instruction, two aligned 16-bit instructions or a mixture of those. The instructions including control and exception information are stored -to a FIFO queue - the instruction prefetch buffer (IPB). The depth of this FIFO can be configured by the `CPU_IPB_ENTRIES` top generic. +to a FIFO queue - the instruction prefetch buffer (IPB). This FIFO has a depth of two entries by default but can be customized +via the `ipb_depth_c` VHDL package constant. The FIFO allows the front-end to do "speculative" instruction fetches, as it keeps fetching the next consecutive instruction all the time. This also allows to decouple front-end (instruction fetch) and back-end (instruction execution) so both modules @@ -695,7 +696,6 @@ Auto-increment of the HPMs can be deactivated individually via the <<_mcountinhi This is a sub-extension of the <<_m_isa_extension>> ISA extension. It implements only the multiplication operations of the `M` extensions and is intended for size-constrained setups that require hardware-based integer multiplications but not hardware-based divisions, which will be computed entirely in software. -This extension requires only ~50% of the hardware utilization of the "full" `M` extension. ==== `Zxcfu` ISA Extension diff --git a/docs/datasheet/soc.adoc b/docs/datasheet/soc.adoc index 8823e6d45..06a3a1125 100644 --- a/docs/datasheet/soc.adoc +++ b/docs/datasheet/soc.adoc @@ -221,7 +221,6 @@ The generic type "`suv(x:y)`" is an abbreviation for "`std_ulogic_vector(x downt 4+^| **CPU Tuning Options** | `FAST_MUL_EN` | boolean | false | Implement fast (but large) full-parallel multipliers (trying to infer DSP blocks). | `FAST_SHIFT_EN` | boolean | false | Implement fast (but large) full-parallel barrel shifters. -| `CPU_IPB_ENTRIES` | natural | 1 | Number of entries in the CPU's instruction prefetch buffer. 4+^| **Physical Memory Protection (<<_pmp_isa_extension>>)** | `PMP_NUM_REGIONS` | natural | 0 | Number of implemented PMP regions (0..16). | `PMP_MIN_GRANULARITY` | natural | 4 | Minimal region granularity in bytes. Has to be a power of two, min 4. @@ -459,23 +458,29 @@ A pending FIRQ has to be explicitly cleared by writing zero to the according <<_ As a 32-bit architecture the NEORV32 can access a 4GB physical address space. By default, this address space is split into six main regions. Each region provides specific _physical memory attributes_ ("PMAs") that define -the access capabilities. +the access capabilities (`rwxac`; `r` = read permission, `w` = execute permission, `x` - execute permission, +`a` = atomic access support, `c` = cached CPU access). .NEORV32 Processor Address Space (Default Configuration) image::address_space.png[900] +.Main Address Regions [cols="<1,^4,^2,<7"] [options="header",grid="rows"] |======================= -| # | Region | PMAs | Description -| 1 | Internal IMEM address space | `rwx` | For instructions (=code) and constants; mapped to the internal <<_instruction_memory_imem>>. -| 2 | Internal DMEM address space | `rwx` | For application runtime data (heap, stack, etc.); mapped to the internal <<_data_memory_dmem>>). -| 3 | Memory-mapped XIP flash | `r-x` | Memory-mapped access to the <<_execute_in_place_module_xip>> SPI flash. -| 4 | Bootloader address space | `r-x` | Read-only memory for the internal <<_bootloader_rom_bootrom>> containing the default <<_bootloader>>. -| 5 | IO/peripheral address space | `rwx` | Processor-internal peripherals / IO devices. -| 6 | The "**void**" | `rwx` | Unmapped address space. All accesses to this region(s) are redirected to the <<_processor_external_memory_interface_wishbone>> (if implemented). +| # | Region | PMAs | Description +| 1 | Internal IMEM address space | `rwxac` | For instructions (=code) and constants; mapped to the internal <<_instruction_memory_imem>>. +| 2 | Internal DMEM address space | `rwxac` | For application runtime data (heap, stack, etc.); mapped to the internal <<_data_memory_dmem>>). +| 3 | Memory-mapped XIP flash | `r-xac` | Memory-mapped access to the <<_execute_in_place_module_xip>> SPI flash. +| 4 | Bootloader address space | `r-xa-` | Read-only memory for the internal <<_bootloader_rom_bootrom>> containing the default <<_bootloader>>. +| 5 | IO/peripheral address space | `rwxa-` | Processor-internal peripherals / IO devices. +| 6 | The "**void**" | `rwxac` | Unmapped address space. All accesses to this region(s) are redirected to the <<_processor_external_memory_interface_wishbone>> (if implemented). |======================= +.Custom PMAs +[NOTE] +Physical memory attributes can be customized (constrained) using the CPU's <<_pmp_isa_extension>>. + The CPU can access all of the 32-bit address space from the instruction fetch interface and also from the data access interface. Both interfaces can be equipped with optional caches (<<_processor_internal_data_cache_dcache>> and <<_processor_internal_instruction_cache_icache>>). The two CPU interfaces are multiplexed by a simple bus switch into diff --git a/docs/datasheet/software.adoc b/docs/datasheet/software.adoc index 0fa88c52f..0b43a155e 100644 --- a/docs/datasheet/software.adoc +++ b/docs/datasheet/software.adoc @@ -265,6 +265,8 @@ The following default compiler flags are used for compiling an application. Thes | `-lgcc` | Make sure we have no unresolved references to internal GCC library subroutines. | `-mno-fdiv` | Use built-in software functions for floating-point divisions and square roots (since the according instructions are not supported yet). | `-g` | Include debugging information/symbols in ELF. +| `-mstrict-align` | Unaligned memory accesses cannot be resolved by the hardware and require emulation. +| `-mbranch-cost=...` | Branches cost a lot cycles on a multi-cycle architecture. |======================= :sectnums: diff --git a/docs/figures/address_space.png b/docs/figures/address_space.png index ba56a5231..2c5f14adb 100644 Binary files a/docs/figures/address_space.png and b/docs/figures/address_space.png differ diff --git a/docs/userguide/application_specific_configuration.adoc b/docs/userguide/application_specific_configuration.adoc index 1bd9895be..5166481ca 100644 --- a/docs/userguide/application_specific_configuration.adoc +++ b/docs/userguide/application_specific_configuration.adoc @@ -23,8 +23,6 @@ multiplications, `FAST_SHIFT_EN => true` use a fast barrel shifter for shift ope * Implement the instruction cache: `ICACHE_EN => true` * Use as many _internal_ memory as possible to reduce memory access latency: `MEM_INT_IMEM_EN => true` and `MEM_INT_DMEM_EN => true`, maximize `MEM_INT_IMEM_SIZE` and `MEM_INT_DMEM_SIZE` -* Increase the CPU's instruction prefetch buffer size: if **no** instruction cache is implemented `CPU_IPB_ENTRIES` should be -quite large * _To be continued..._ @@ -53,7 +51,6 @@ also reduces program code size by approximately 30%. * If not explicitly used/required, exclude the CPU standard counters `[m]instret[h]` (number of instruction) and `[m]cycle[h]` (number of cycles) from synthesis by disabling the `Zicntr` ISA extension (note, this is not RISC-V compliant). -* Reduce the CPU's prefetch buffer size (`CPU_IPB_ENTRIES`) to its minimum (=1). * Map CPU shift operations to a small and iterative shifter unit (`FAST_SHIFT_EN => false`). * If you have unused DSP block available, you can map multiplication operations to those slices instead of using LUTs to implement the multiplier (`FAST_MUL_EN => true`). diff --git a/rtl/core/neorv32_cpu.vhd b/rtl/core/neorv32_cpu.vhd index 28a0828fc..3268e60df 100644 --- a/rtl/core/neorv32_cpu.vhd +++ b/rtl/core/neorv32_cpu.vhd @@ -66,7 +66,6 @@ entity neorv32_cpu is -- Extension Options -- FAST_MUL_EN : boolean; -- use DSPs for M extension's multiplier FAST_SHIFT_EN : boolean; -- use barrel shifter for shift operations - CPU_IPB_ENTRIES : natural; -- entries in instruction prefetch buffer, has to be a power of 2, min 1 -- Physical Memory Protection (PMP) -- PMP_NUM_REGIONS : natural; -- number of regions (0..16) PMP_MIN_GRANULARITY : natural; -- minimal region granularity in bytes, has to be a power of 2, min 4 bytes @@ -99,14 +98,10 @@ end neorv32_cpu; architecture neorv32_cpu_rtl of neorv32_cpu is - -- local constants: additional register file read ports -- + -- auto-configuration -- constant regfile_rs3_en_c : boolean := CPU_EXTENSION_RISCV_Zxcfu or CPU_EXTENSION_RISCV_Zfinx; -- 3rd register file read port (rs3) constant regfile_rs4_en_c : boolean := CPU_EXTENSION_RISCV_Zxcfu; -- 4th register file read port (rs4) - -- local constant: instruction prefetch buffer depth -- - constant ipb_override_c : boolean := (CPU_EXTENSION_RISCV_C = true) and (CPU_IPB_ENTRIES < 2); -- override IPB size: set to 2? - constant ipb_depth_c : natural := cond_sel_natural_f(ipb_override_c, 2, CPU_IPB_ENTRIES); - -- local signals -- signal ctrl : ctrl_bus_t; -- main control bus signal imm : std_ulogic_vector(XLEN-1 downto 0); -- immediate @@ -120,7 +115,7 @@ architecture neorv32_cpu_rtl of neorv32_cpu is signal mem_rdata : std_ulogic_vector(XLEN-1 downto 0); -- memory read data signal cp_done : std_ulogic; -- ALU co-processor operation done signal alu_exc : std_ulogic; -- ALU exception - signal bus_d_wait : std_ulogic; -- wait for current bus data access + signal bus_d_wait : std_ulogic; -- wait for current data bus access signal csr_rdata : std_ulogic_vector(XLEN-1 downto 0); -- csr read data signal mar : std_ulogic_vector(XLEN-1 downto 0); -- memory address register signal ma_load : std_ulogic; -- misaligned load data address @@ -143,7 +138,7 @@ begin -- ------------------------------------------------------------------------------------------- -- say hello -- assert false report - "The NEORV32 RISC-V Processor (Version 0x" & to_hstring32_f(hw_version_c) & ") - github.com/stnolting/neorv32" severity note; + "The NEORV32 RISC-V Processor Version 0x" & to_hstring32_f(hw_version_c) & " - github.com/stnolting/neorv32" severity note; -- CPU ISA configuration -- assert false report @@ -175,12 +170,6 @@ begin assert not (CPU_BOOT_ADDR(1 downto 0) /= "00") report "NEORV32 CPU CONFIG ERROR! has to be 32-bit aligned." severity error; - -- Instruction prefetch buffer -- - assert not (is_power_of_two_f(CPU_IPB_ENTRIES) = false) report - "NEORV32 CPU CONFIG ERROR! Number of entries in instruction prefetch buffer has to be a power of two." severity error; - assert not (ipb_override_c = true) report - "NEORV32 CPU CONFIG WARNING! Overriding configuration (setting =2) because C ISA extension is enabled." severity warning; - -- PMP -- assert not (PMP_NUM_REGIONS > 16) report "NEORV32 CPU CONFIG ERROR! Number of PMP regions out of valid range (0..16)." severity error; @@ -233,7 +222,6 @@ begin -- Tuning Options -- FAST_MUL_EN => FAST_MUL_EN, -- use DSPs for M extension's multiplier FAST_SHIFT_EN => FAST_SHIFT_EN, -- use barrel shifter for shift operations - CPU_IPB_ENTRIES => ipb_depth_c, -- entries is instruction prefetch buffer, has to be a power of 2, min 1 -- Physical memory protection (PMP) -- PMP_NUM_REGIONS => PMP_NUM_REGIONS, -- number of regions (0..16) PMP_MIN_GRANULARITY => PMP_MIN_GRANULARITY, -- minimal region granularity in bytes, has to be a power of 2, min 4 bytes @@ -323,10 +311,10 @@ begin csr_i => csr_rdata, -- CSR read data pc2_i => next_pc, -- next PC -- data output -- - rs1_o => rs1, -- operand 1 - rs2_o => rs2, -- operand 2 - rs3_o => rs3, -- operand 3 - rs4_o => rs4 -- operand 4 + rs1_o => rs1, -- rs1 + rs2_o => rs2, -- rs2 + rs3_o => rs3, -- rs3 + rs4_o => rs4 -- rs4 ); diff --git a/rtl/core/neorv32_cpu_control.vhd b/rtl/core/neorv32_cpu_control.vhd index 8b979f696..9fdfb4798 100644 --- a/rtl/core/neorv32_cpu_control.vhd +++ b/rtl/core/neorv32_cpu_control.vhd @@ -76,7 +76,6 @@ entity neorv32_cpu_control is -- Tuning Options -- FAST_MUL_EN : boolean; -- use DSPs for M extension's multiplier FAST_SHIFT_EN : boolean; -- use barrel shifter for shift operations - CPU_IPB_ENTRIES : natural; -- entries in instruction prefetch buffer, has to be a power of 2, min 1 -- Physical memory protection (PMP) -- PMP_NUM_REGIONS : natural; -- number of regions (0..16) PMP_MIN_GRANULARITY : natural; -- minimal region granularity in bytes, has to be a power of 2, min 4 bytes @@ -111,14 +110,12 @@ entity neorv32_cpu_control is csr_rdata_o : out std_ulogic_vector(XLEN-1 downto 0); -- CSR read data -- FPU interface -- fpu_flags_i : in std_ulogic_vector(4 downto 0); -- exception flags - -- debug mode (halt) request -- - db_halt_req_i : in std_ulogic; - -- interrupts (risc-v compliant) -- + -- interrupts -- + db_halt_req_i : in std_ulogic; -- debug mode (halt) request msi_i : in std_ulogic; -- machine software interrupt mei_i : in std_ulogic; -- machine external interrupt mti_i : in std_ulogic; -- machine timer interrupt - -- fast interrupts (custom) -- - firq_i : in std_ulogic_vector(15 downto 0); + firq_i : in std_ulogic_vector(15 downto 0); -- fast interrupts -- physical memory protection -- pmp_addr_o : out pmp_addr_if_t; -- addresses pmp_ctrl_o : out pmp_ctrl_if_t; -- configs @@ -133,9 +130,10 @@ end neorv32_cpu_control; architecture neorv32_cpu_control_rtl of neorv32_cpu_control is - -- HPM counter width - high/low parts -- - constant hpm_cnt_lo_width_c : natural := natural(cond_sel_int_f(boolean(HPM_CNT_WIDTH < 32), HPM_CNT_WIDTH, 32)); - constant hpm_cnt_hi_width_c : natural := natural(cond_sel_int_f(boolean(HPM_CNT_WIDTH > 32), HPM_CNT_WIDTH-32, 0)); + -- HPM counter auto-configuration -- + constant hpm_num_c : natural := cond_sel_natural_f(CPU_EXTENSION_RISCV_Zihpm, HPM_NUM_CNTS, 0); + constant hpm_cnt_lo_width_c : natural := natural(cond_sel_natural_f(boolean(HPM_CNT_WIDTH < 32), HPM_CNT_WIDTH, 32)); -- width low word + constant hpm_cnt_hi_width_c : natural := natural(cond_sel_natural_f(boolean(HPM_CNT_WIDTH > 32), HPM_CNT_WIDTH-32, 0)); -- width high word -- instruction fetch engine -- type fetch_engine_state_t is (IF_RESTART, IF_REQUEST, IF_PENDING, IF_WAIT); @@ -298,7 +296,7 @@ architecture neorv32_cpu_control_rtl of neorv32_cpu_control is signal csr : csr_t; -- hpm event configuration CSRs (first 3 entries are just dummies) -- - type hpmevent_cfg_t is array (0 to HPM_NUM_CNTS-1) of std_ulogic_vector(hpmcnt_event_size_c-1 downto 0); + type hpmevent_cfg_t is array (0 to hpm_num_c-1) of std_ulogic_vector(hpmcnt_event_size_c-1 downto 0); type hpmevent_rd_t is array (0 to 31) of std_ulogic_vector(XLEN-1 downto 0); type hpmevent_t is record we : std_ulogic_vector(31 downto 0); @@ -416,7 +414,7 @@ begin when IF_PENDING => -- wait for bus response and write instruction data to prefetch buffer -- ------------------------------------------------------------ if (fetch_engine.resp = '1') then -- wait for bus response - fetch_engine.pc <= std_ulogic_vector(unsigned(fetch_engine.pc) + 4); + fetch_engine.pc <= std_ulogic_vector(unsigned(fetch_engine.pc) + 4); -- next word fetch_engine.unaligned <= '0'; if (fetch_engine.restart = '1') or (fetch_engine.reset = '1') then -- restart request (fast) fetch_engine.state <= IF_RESTART; @@ -475,7 +473,7 @@ begin for i in 0 to 1 generate -- low half-word and high half-word (+status) prefetch_buffer_inst: entity neorv32.neorv32_fifo generic map ( - FIFO_DEPTH => CPU_IPB_ENTRIES, -- number of fifo entries; has to be a power of two; min 1 + FIFO_DEPTH => ipb_depth_c, -- number of fifo entries; has to be a power of two FIFO_WIDTH => ipb.wdata(i)'length, -- size of data elements in fifo FIFO_RSYNC => false, -- we NEED to read data asynchronously FIFO_SAFE => false -- no safe access required (ensured by FIFO-external control) @@ -502,6 +500,29 @@ begin -- Instruction Issue (decompress 16-bit instructions and assemble a 32-bit instruction word) -- **************************************************************************************************************************** + -- Compressed Instructions Decoder -------------------------------------------------------- + -- ------------------------------------------------------------------------------------------- + neorv32_cpu_decompressor_inst_true: + if (CPU_EXTENSION_RISCV_C = true) generate + neorv32_cpu_decompressor_inst: entity neorv32.neorv32_cpu_decompressor + generic map ( + FPU_ENABLE => CPU_EXTENSION_RISCV_Zfinx -- floating-point instructions enabled + ) + port map ( + ci_instr16_i => issue_engine.ci_i16, -- compressed instruction + ci_instr32_o => issue_engine.ci_i32 -- decompressed instruction + ); + end generate; + + neorv32_cpu_decompressor_inst_false: + if (CPU_EXTENSION_RISCV_C = false) generate + issue_engine.ci_i32 <= (others => '0'); + end generate; + + -- 16-bit instructions: half-word select -- + issue_engine.ci_i16 <= ipb.rdata(0)(15 downto 0) when (issue_engine.align = '0') else ipb.rdata(1)(15 downto 0); + + -- Issue Engine FSM (required only if C extension is enabled) ----------------------------- -- ------------------------------------------------------------------------------------------- issue_engine_enabled: @@ -562,29 +583,6 @@ begin ipb.re(1) <= '1' when (issue_engine.valid(1) = '1') and (issue_engine.ack = '1') else '0'; - -- Compressed Instructions Decoding ------------------------------------------------------- - -- ------------------------------------------------------------------------------------------- - neorv32_cpu_decompressor_inst_true: - if (CPU_EXTENSION_RISCV_C = true) generate - neorv32_cpu_decompressor_inst: entity neorv32.neorv32_cpu_decompressor - generic map ( - FPU_ENABLE => CPU_EXTENSION_RISCV_Zfinx -- floating-point instructions enabled - ) - port map ( - ci_instr16_i => issue_engine.ci_i16, -- compressed instruction - ci_instr32_o => issue_engine.ci_i32 -- decompressed instruction - ); - end generate; - - neorv32_cpu_decompressor_inst_false: - if (CPU_EXTENSION_RISCV_C = false) generate - issue_engine.ci_i32 <= (others => '0'); - end generate; - - -- 16-bit instructions: half-word select -- - issue_engine.ci_i16 <= ipb.rdata(0)(15 downto 0) when (issue_engine.align = '0') else ipb.rdata(1)(15 downto 0); - - -- **************************************************************************************************************************** -- Instruction Execution -- **************************************************************************************************************************** @@ -726,19 +724,13 @@ begin decode_aux.is_b_imm <= '0'; decode_aux.is_b_reg <= '0'; decode_aux.is_zicond <= '0'; - decode_aux.rs1_zero <= '0'; - decode_aux.rd_zero <= '0'; - - -- simplified opcode -- - decode_aux.opcode <= execute_engine.ir(instr_opcode_msb_c downto instr_opcode_lsb_c+2) & "11"; -- is ATOMIC operation? -- - if (CPU_EXTENSION_RISCV_A = true) then -- ATOMIC implemented at all? - if (execute_engine.ir(instr_funct3_msb_c downto instr_funct3_lsb_c) = "010") and - (execute_engine.ir(instr_funct7_msb_c downto instr_funct7_lsb_c+3) = "0001") then - decode_aux.is_a_lr <= not execute_engine.ir(instr_funct7_lsb_c+2); -- LR.W - decode_aux.is_a_sc <= execute_engine.ir(instr_funct7_lsb_c+2); -- SC.W - end if; + if (CPU_EXTENSION_RISCV_A = true) and -- ATOMIC implemented at all? + (execute_engine.ir(instr_funct3_msb_c downto instr_funct3_lsb_c) = "010") and + (execute_engine.ir(instr_funct7_msb_c downto instr_funct7_lsb_c+3) = "0001") then + decode_aux.is_a_lr <= not execute_engine.ir(instr_funct7_lsb_c+2); -- LR.W + decode_aux.is_a_sc <= execute_engine.ir(instr_funct7_lsb_c+2); -- SC.W end if; -- is BITMANIP instruction? -- @@ -754,7 +746,7 @@ begin )) or ((execute_engine.ir(instr_funct7_msb_c downto instr_funct7_lsb_c) = "0110000") and (execute_engine.ir(instr_funct3_msb_c downto instr_funct3_lsb_c) = "101")) or -- RORI ((execute_engine.ir(instr_funct7_msb_c downto instr_funct7_lsb_c) = "0010100") and (execute_engine.ir(instr_funct3_msb_c downto instr_funct3_lsb_c) = "101") and - (execute_engine.ir(instr_funct12_lsb_c+4 downto instr_funct12_lsb_c) = "00111")) or -- ORCB + (execute_engine.ir(instr_funct12_lsb_c+4 downto instr_funct12_lsb_c) = "00111")) or -- ORCB ((execute_engine.ir(instr_funct7_msb_c downto instr_funct7_lsb_c) = "0100100") and (execute_engine.ir(instr_funct3_msb_c-1 downto instr_funct3_lsb_c) = "01")) or -- BCLRI / BEXTI ((execute_engine.ir(instr_funct7_msb_c downto instr_funct7_lsb_c) = "0110100") and (execute_engine.ir(instr_funct3_msb_c-1 downto instr_funct3_lsb_c) = "01")) or -- REV8 / BINVI ((execute_engine.ir(instr_funct7_msb_c downto instr_funct7_lsb_c) = "0010100") and (execute_engine.ir(instr_funct3_msb_c downto instr_funct3_lsb_c) = "001")) then -- BSETI @@ -813,16 +805,15 @@ begin (execute_engine.ir(instr_funct3_msb_c) = '1') and (execute_engine.ir(instr_funct3_lsb_c) = '1') then decode_aux.is_zicond <= '1'; end if; - - -- register/uimm5 checks -- - if (execute_engine.ir(instr_rs1_msb_c downto instr_rs1_lsb_c) = "00000") then - decode_aux.rs1_zero <= '1'; - end if; - if (execute_engine.ir(instr_rd_msb_c downto instr_rd_lsb_c) = "00000") then - decode_aux.rd_zero <= '1'; - end if; end process decode_helper; + -- register/uimm5 checks -- + decode_aux.rs1_zero <= '1' when (execute_engine.ir(instr_rs1_msb_c downto instr_rs1_lsb_c) = "00000") else '0'; + decode_aux.rd_zero <= '1' when (execute_engine.ir(instr_rd_msb_c downto instr_rd_lsb_c ) = "00000") else '0'; + + -- simplified opcode -- + decode_aux.opcode <= execute_engine.ir(instr_opcode_msb_c downto instr_opcode_lsb_c+2) & "11"; + -- CSR access address -- csr.addr <= execute_engine.ir(instr_imm12_msb_c downto instr_imm12_lsb_c); @@ -1055,7 +1046,7 @@ begin if (trap_ctrl.exc_buf(exc_iillegal_c) = '0') then -- update only if not illegal instruction execute_engine.pc_we <= '1'; -- update PC with branch DST; will be overridden in DISPATCH if branch not taken end if; - if (execute_engine.ir(instr_opcode_lsb_c+2) = '1') or (execute_engine.branch_taken = '1') then -- JAL/JALR or taken branch + if (execute_engine.ir(instr_opcode_lsb_c+2) = '1') or (execute_engine.branch_taken = '1') then -- JAL[R] or taken branch fetch_engine.reset <= '1'; -- reset instruction fetch starting at modified PC execute_engine.state_nxt <= BRANCHED; else @@ -1126,9 +1117,9 @@ begin when funct12_ebreak_c => trap_ctrl.break_point <= '1'; -- ebreak when funct12_mret_c => execute_engine.state_nxt <= TRAP_EXIT; -- mret when funct12_dret_c => execute_engine.state_nxt <= TRAP_EXIT; debug_ctrl.dret <= '1'; -- dret - when others => execute_engine.state_nxt <= CPU_SLEEP; -- "funct12_wfi_c" - wfi/sleep or illegal + when others => execute_engine.state_nxt <= CPU_SLEEP; -- "funct12_wfi_c" - wfi/sleep end case; - else -- CSR ACCESS - no CSR will be altered if illegal instruction + else -- CSR ACCESS - no CSR/GPR will be altered if illegal instruction if (execute_engine.ir(instr_funct3_msb_c downto instr_funct3_lsb_c) = funct3_csrrw_c) or -- CSRRW: always write CSR (execute_engine.ir(instr_funct3_msb_c downto instr_funct3_lsb_c) = funct3_csrrwi_c) or -- CSRRWI: always write CSR (decode_aux.rs1_zero = '0') then -- CSRR(S/C)(I): write CSR if rs1/imm5 is NOT zero @@ -1161,7 +1152,7 @@ begin ctrl_o.alu_frm <= csr.frm; ctrl_o.alu_cp_trig <= ctrl.alu_cp_trig; - -- bus interface -- + -- data bus interface -- ctrl_o.bus_req_rd <= ctrl.bus_req_rd; ctrl_o.bus_req_wr <= ctrl.bus_req_wr; ctrl_o.bus_mo_we <= ctrl.bus_mo_we; @@ -1458,7 +1449,7 @@ begin -- Exception Buffer ----------------------------------------------------- -- If several exception sources trigger at once, all the requests will -- stay active until the trap environment is started. Only the exception - -- with highest priority will be used to update the MCAUSE CSR. The + -- with highest priority will be used to update the MCAUSE CSR. All -- remaining ones will be discarded. -- ---------------------------------------------------------------------- @@ -1496,9 +1487,10 @@ begin end if; - -- Interrupt Pending Buffer --------------------------------------------- + -- Interrupt-Pending Buffer --------------------------------------------- -- Once triggered, the fast interrupt requests stay active until - -- explicitly cleared via the MIP CSR. + -- explicitly cleared via the MIP CSR. The RISC-V standard interrupts + -- have to stay high until cleared by a platform-specific mechanism. -- ---------------------------------------------------------------------- -- RISC-V machine interrupts -- @@ -1554,15 +1546,13 @@ begin trap_ctrl.env_pending <= '0'; elsif rising_edge(clk_i) then trap_ctrl.wakeup <= or_reduce_f(trap_ctrl.irq_buf); -- wakeup from sleep on any (enabled! #583) pending IRQ (including debug IRQs) - if (trap_ctrl.env_pending = '0') then -- no started trap handler yet + if (trap_ctrl.env_pending = '0') then -- no pending trap environment yet -- trigger IRQ only in EXECUTE state to continue execution even on permanent IRQ if (trap_ctrl.exc_fire = '1') or ((trap_ctrl.irq_fire = '1') and (execute_engine.state = EXECUTE)) then trap_ctrl.env_pending <= '1'; -- now execute engine can start trap handling end if; - else -- trap environment ready to start - if (trap_ctrl.env_enter = '1') then -- start of trap handler acknowledged by execute engine - trap_ctrl.env_pending <= '0'; - end if; + elsif (trap_ctrl.env_enter = '1') then -- start of trap environment acknowledged by execute engine + trap_ctrl.env_pending <= '0'; end if; end if; end process trap_controller; @@ -1973,7 +1963,7 @@ begin -- Physical Memory Protection (PMP) CSRs -------------------------------------------------- -- ------------------------------------------------------------------------------------------- - pmp_en_gen: + pmp_gen_enable: if (PMP_NUM_REGIONS > 0) generate -- write enable decoder -- @@ -2000,6 +1990,7 @@ begin pmp.cfg(i) <= (others => '0'); pmp.addr(i) <= (others => '0'); elsif rising_edge(clk_i) then + -- configuration -- if (pmp.we_cfg(i/4) = '1') and (pmp.cfg(i)(7) = '0') then -- unlocked write access pmp.cfg(i)(2 downto 0) <= csr.wdata((i mod 4)*8+2 downto (i mod 4)*8+0); -- X (execute), W (write), R (read) @@ -2011,6 +2002,7 @@ begin pmp.cfg(i)(6 downto 5) <= "00"; -- reserved pmp.cfg(i)(7) <= csr.wdata((i mod 4)*8+7); -- L (locked) end if; + -- address -- if (pmp.we_addr(i) = '1') and (pmp.cfg(i)(7) = '0') then -- unlocked write access if (i < PMP_NUM_REGIONS-1) then @@ -2021,43 +2013,54 @@ begin pmp.addr(i) <= "00" & csr.wdata(XLEN-3 downto 0); end if; end if; + end if; end process pmp_reg; end generate; - end generate; + -- PMP output to bus unit and CSR read-back -- + pmp_connect: process(pmp) + begin + pmp_ctrl_o <= (others => (others => '0')); + pmp_addr_o <= (others => (others => '0')); + pmp_cfg_rd <= (others => (others => '0')); + pmp_addr_rd <= (others => (others => '0')); + for i in 0 to PMP_NUM_REGIONS-1 loop + pmp_ctrl_o(i) <= pmp.cfg(i); + pmp_addr_o(i) <= pmp.addr(i) & "00"; -- word aligned address + pmp_cfg_rd(i/4)(8*(i mod 4)+7 downto 8*(i mod 4)+0) <= pmp.cfg(i); + pmp_addr_rd(i)(XLEN-1 downto index_size_f(PMP_MIN_GRANULARITY)-2) <= pmp.addr(i)(XLEN-1 downto index_size_f(PMP_MIN_GRANULARITY)-2); + if (PMP_MIN_GRANULARITY = 8) then -- bit [G-1] reads as zero in TOR or OFF mode + if (pmp.cfg(i)(4) = '0') then -- TOR/OFF + pmp_addr_rd(i)(index_size_f(PMP_MIN_GRANULARITY)-1) <= '0'; + end if; + elsif (PMP_MIN_GRANULARITY > 8) then + -- in NAPOT mode, bits [G-2:0] must read as one + pmp_addr_rd(i)(index_size_f(PMP_MIN_GRANULARITY)-2 downto 0) <= (others => '1'); + -- in TOR or OFF mode, bits [G-1:0] must read as zero + if (pmp.cfg(i)(4) = '0') then -- TOR/OFF + pmp_addr_rd(i)(index_size_f(PMP_MIN_GRANULARITY)-1 downto 0) <= (others => '0'); + end if; + end if; + end loop; + end process pmp_connect; - -- PMP output to bus unit and CSR read-back -- - pmp_connect: process(pmp) - begin + end generate; -- /pmp_gen_enable + + + -- no PMP implemented -- + pmp_gen_disable: + if (PMP_NUM_REGIONS = 0) generate pmp_ctrl_o <= (others => (others => '0')); pmp_addr_o <= (others => (others => '0')); pmp_cfg_rd <= (others => (others => '0')); pmp_addr_rd <= (others => (others => '0')); - for i in 0 to PMP_NUM_REGIONS-1 loop - pmp_ctrl_o(i) <= pmp.cfg(i); - pmp_addr_o(i) <= pmp.addr(i) & "00"; -- word aligned address - pmp_cfg_rd(i/4)(8*(i mod 4)+7 downto 8*(i mod 4)+0) <= pmp.cfg(i); - pmp_addr_rd(i)(XLEN-1 downto index_size_f(PMP_MIN_GRANULARITY)-2) <= pmp.addr(i)(XLEN-1 downto index_size_f(PMP_MIN_GRANULARITY)-2); - if (PMP_MIN_GRANULARITY = 8) then -- bit [G-1] reads as zero in TOR or OFF mode - if (pmp.cfg(i)(4) = '0') then -- TOR/OFF - pmp_addr_rd(i)(index_size_f(PMP_MIN_GRANULARITY)-1) <= '0'; - end if; - elsif (PMP_MIN_GRANULARITY > 8) then - -- in NAPOT mode, bits [G-2:0] must read as one - pmp_addr_rd(i)(index_size_f(PMP_MIN_GRANULARITY)-2 downto 0) <= (others => '1'); - -- in TOR or OFF mode, bits [G-1:0] must read as zero - if (pmp.cfg(i)(4) = '0') then -- TOR/OFF - pmp_addr_rd(i)(index_size_f(PMP_MIN_GRANULARITY)-1 downto 0) <= (others => '0'); - end if; - end if; - end loop; - end process pmp_connect; - - - -- Hardware Performance Monitors (HMP) Counter Event Configuration CSRs ------------------- + end generate; -- /pmp_gen_disable + + + -- Hardware Performance Monitors (HPM) - Counter Event Configuration CSRs ----------------- -- ------------------------------------------------------------------------------------------- - hpm_en_gen: + hpm_gen_enable: if (CPU_EXTENSION_RISCV_Zihpm = true) generate -- write enable decoder -- @@ -2071,7 +2074,7 @@ begin -- HPM event registers -- hpmevent_reg_gen: - for i in 0 to HPM_NUM_CNTS-1 generate + for i in 0 to hpm_num_c-1 generate hpmevent_reg: process(rstn_i, clk_i) begin if (rstn_i = '0') then @@ -2088,13 +2091,22 @@ begin hpm_event_connect: process(hpmevent) begin hpmevent_rd <= (others => (others => '0')); - for i in 3 to (HPM_NUM_CNTS+3)-1 loop + for i in 3 to (hpm_num_c+3)-1 loop hpmevent_rd(i)(hpmcnt_event_size_c-1 downto 0) <= hpmevent.cfg(i-3); hpmevent_rd(i)(hpmcnt_event_tm_c) <= '0'; -- time, unused/reserved end loop; end process hpm_event_connect; - end generate; + end generate; -- /hpm_gen_enable + + + -- no HPMs implemented -- + hpm_gen_disable: + if (CPU_EXTENSION_RISCV_Zihpm = false) generate + hpmevent.we <= (others => '0'); + hpmevent.cfg <= (others => (others => '0')); + hpmevent_rd <= (others => (others => '0')); + end generate; -- /hpm_gen_disable -- Control and Status Registers - Read Access --------------------------------------------- @@ -2139,12 +2151,11 @@ begin 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) + csr.rdata(08) <= bool_to_ulogic_f(not CPU_EXTENSION_RISCV_E); -- I CPU extension (if not E) csr.rdata(12) <= bool_to_ulogic_f(CPU_EXTENSION_RISCV_M); -- M CPU extension csr.rdata(20) <= bool_to_ulogic_f(CPU_EXTENSION_RISCV_U); -- U CPU extension csr.rdata(23) <= '1'; -- X CPU extension (non-standard extensions / NEORV32-specific) - csr.rdata(30) <= '1'; -- 32-bit architecture (MXL lo) - csr.rdata(31) <= '0'; -- 32-bit architecture (MXL hi) + csr.rdata(31 downto 30) <= "01"; -- machine XLEN = 32 when csr_mie_c => -- machine interrupt-enable register csr.rdata(03) <= csr.mie_msi; @@ -2159,8 +2170,8 @@ begin if (CPU_EXTENSION_RISCV_U = true) then csr.rdata(0) <= csr.mcounteren(0); -- allow user-level access to cycle[h] csr.rdata(2) <= csr.mcounteren(2); -- allow user-level access to instret[h] - if (CPU_EXTENSION_RISCV_Zihpm = true) and (HPM_NUM_CNTS > 0) then -- any HPMs implemented? - csr.rdata((HPM_NUM_CNTS+3)-1 downto 3) <= csr.mcounteren((HPM_NUM_CNTS+3)-1 downto 3); -- allow user-level access to all available hpmcounter*[h] CSRs + if (CPU_EXTENSION_RISCV_Zihpm = true) and (hpm_num_c > 0) then -- any HPMs implemented? + csr.rdata((hpm_num_c+3)-1 downto 3) <= csr.mcounteren((hpm_num_c+3)-1 downto 3); -- allow user-level access to all available hpmcounter*[h] CSRs end if; end if; @@ -2193,15 +2204,28 @@ begin -- physical memory protection -- -- -------------------------------------------------------------------- -- region configuration -- - when csr_pmpcfg0_c | csr_pmpcfg1_c | csr_pmpcfg2_c | csr_pmpcfg3_c => - if (PMP_NUM_REGIONS > 0) then csr.rdata <= pmp_cfg_rd(to_integer(unsigned(csr.addr(1 downto 0)))); end if; + when csr_pmpcfg0_c => if (PMP_NUM_REGIONS > 00) then csr.rdata <= pmp_cfg_rd(0); end if; + when csr_pmpcfg1_c => if (PMP_NUM_REGIONS > 04) then csr.rdata <= pmp_cfg_rd(1); end if; + when csr_pmpcfg2_c => if (PMP_NUM_REGIONS > 08) then csr.rdata <= pmp_cfg_rd(2); end if; + when csr_pmpcfg3_c => if (PMP_NUM_REGIONS > 12) then csr.rdata <= pmp_cfg_rd(3); end if; -- region address -- - when csr_pmpaddr0_c | csr_pmpaddr1_c | csr_pmpaddr2_c | csr_pmpaddr3_c | - csr_pmpaddr4_c | csr_pmpaddr5_c | csr_pmpaddr6_c | csr_pmpaddr7_c | - csr_pmpaddr8_c | csr_pmpaddr9_c | csr_pmpaddr10_c | csr_pmpaddr11_c | - csr_pmpaddr12_c | csr_pmpaddr13_c | csr_pmpaddr14_c | csr_pmpaddr15_c => - if (PMP_NUM_REGIONS > 0) then csr.rdata <= pmp_addr_rd(to_integer(unsigned(csr.addr(3 downto 0)))); end if; + when csr_pmpaddr0_c => if (PMP_NUM_REGIONS > 00) then csr.rdata <= pmp_addr_rd(00); end if; + when csr_pmpaddr1_c => if (PMP_NUM_REGIONS > 01) then csr.rdata <= pmp_addr_rd(01); end if; + when csr_pmpaddr2_c => if (PMP_NUM_REGIONS > 02) then csr.rdata <= pmp_addr_rd(02); end if; + when csr_pmpaddr3_c => if (PMP_NUM_REGIONS > 03) then csr.rdata <= pmp_addr_rd(03); end if; + when csr_pmpaddr4_c => if (PMP_NUM_REGIONS > 04) then csr.rdata <= pmp_addr_rd(04); end if; + when csr_pmpaddr5_c => if (PMP_NUM_REGIONS > 05) then csr.rdata <= pmp_addr_rd(05); end if; + when csr_pmpaddr6_c => if (PMP_NUM_REGIONS > 06) then csr.rdata <= pmp_addr_rd(06); end if; + when csr_pmpaddr7_c => if (PMP_NUM_REGIONS > 07) then csr.rdata <= pmp_addr_rd(07); end if; + when csr_pmpaddr8_c => if (PMP_NUM_REGIONS > 08) then csr.rdata <= pmp_addr_rd(08); end if; + when csr_pmpaddr9_c => if (PMP_NUM_REGIONS > 09) then csr.rdata <= pmp_addr_rd(09); end if; + when csr_pmpaddr10_c => if (PMP_NUM_REGIONS > 10) then csr.rdata <= pmp_addr_rd(10); end if; + when csr_pmpaddr11_c => if (PMP_NUM_REGIONS > 11) then csr.rdata <= pmp_addr_rd(11); end if; + when csr_pmpaddr12_c => if (PMP_NUM_REGIONS > 12) then csr.rdata <= pmp_addr_rd(12); end if; + when csr_pmpaddr13_c => if (PMP_NUM_REGIONS > 13) then csr.rdata <= pmp_addr_rd(13); end if; + when csr_pmpaddr14_c => if (PMP_NUM_REGIONS > 14) then csr.rdata <= pmp_addr_rd(14); end if; + when csr_pmpaddr15_c => if (PMP_NUM_REGIONS > 15) then csr.rdata <= pmp_addr_rd(15); end if; -- machine counter setup -- -- -------------------------------------------------------------------- @@ -2210,108 +2234,108 @@ begin csr.rdata(0) <= csr.mcountinhibit(0); -- inhibit [m]cycle[h] counter csr.rdata(2) <= csr.mcountinhibit(2); -- inhibit [m]instret[h] counter end if; - if (CPU_EXTENSION_RISCV_Zihpm = true) and (HPM_NUM_CNTS > 0) then -- any HPMs implemented? - csr.rdata((HPM_NUM_CNTS+3)-1 downto 3) <= csr.mcountinhibit((HPM_NUM_CNTS+3)-1 downto 3); -- inhibit [m]hpmcounter*[h] counter + if (CPU_EXTENSION_RISCV_Zihpm = true) and (hpm_num_c > 0) then -- any HPMs implemented? + csr.rdata((hpm_num_c+3)-1 downto 3) <= csr.mcountinhibit((hpm_num_c+3)-1 downto 3); -- inhibit [m]hpmcounter*[h] counter end if; -- HPM event select -- - when csr_mhpmevent3_c => if (CPU_EXTENSION_RISCV_Zihpm) and (HPM_NUM_CNTS > 00) then csr.rdata <= hpmevent_rd(03); end if; - when csr_mhpmevent4_c => if (CPU_EXTENSION_RISCV_Zihpm) and (HPM_NUM_CNTS > 01) then csr.rdata <= hpmevent_rd(04); end if; - when csr_mhpmevent5_c => if (CPU_EXTENSION_RISCV_Zihpm) and (HPM_NUM_CNTS > 02) then csr.rdata <= hpmevent_rd(05); end if; - when csr_mhpmevent6_c => if (CPU_EXTENSION_RISCV_Zihpm) and (HPM_NUM_CNTS > 03) then csr.rdata <= hpmevent_rd(06); end if; - when csr_mhpmevent7_c => if (CPU_EXTENSION_RISCV_Zihpm) and (HPM_NUM_CNTS > 04) then csr.rdata <= hpmevent_rd(07); end if; - when csr_mhpmevent8_c => if (CPU_EXTENSION_RISCV_Zihpm) and (HPM_NUM_CNTS > 05) then csr.rdata <= hpmevent_rd(08); end if; - when csr_mhpmevent9_c => if (CPU_EXTENSION_RISCV_Zihpm) and (HPM_NUM_CNTS > 06) then csr.rdata <= hpmevent_rd(09); end if; - when csr_mhpmevent10_c => if (CPU_EXTENSION_RISCV_Zihpm) and (HPM_NUM_CNTS > 07) then csr.rdata <= hpmevent_rd(10); end if; - when csr_mhpmevent11_c => if (CPU_EXTENSION_RISCV_Zihpm) and (HPM_NUM_CNTS > 08) then csr.rdata <= hpmevent_rd(11); end if; - when csr_mhpmevent12_c => if (CPU_EXTENSION_RISCV_Zihpm) and (HPM_NUM_CNTS > 09) then csr.rdata <= hpmevent_rd(12); end if; - when csr_mhpmevent13_c => if (CPU_EXTENSION_RISCV_Zihpm) and (HPM_NUM_CNTS > 10) then csr.rdata <= hpmevent_rd(13); end if; - when csr_mhpmevent14_c => if (CPU_EXTENSION_RISCV_Zihpm) and (HPM_NUM_CNTS > 11) then csr.rdata <= hpmevent_rd(14); end if; - when csr_mhpmevent15_c => if (CPU_EXTENSION_RISCV_Zihpm) and (HPM_NUM_CNTS > 12) then csr.rdata <= hpmevent_rd(15); end if; - when csr_mhpmevent16_c => if (CPU_EXTENSION_RISCV_Zihpm) and (HPM_NUM_CNTS > 13) then csr.rdata <= hpmevent_rd(16); end if; - when csr_mhpmevent17_c => if (CPU_EXTENSION_RISCV_Zihpm) and (HPM_NUM_CNTS > 14) then csr.rdata <= hpmevent_rd(17); end if; - when csr_mhpmevent18_c => if (CPU_EXTENSION_RISCV_Zihpm) and (HPM_NUM_CNTS > 15) then csr.rdata <= hpmevent_rd(18); end if; - when csr_mhpmevent19_c => if (CPU_EXTENSION_RISCV_Zihpm) and (HPM_NUM_CNTS > 16) then csr.rdata <= hpmevent_rd(19); end if; - when csr_mhpmevent20_c => if (CPU_EXTENSION_RISCV_Zihpm) and (HPM_NUM_CNTS > 17) then csr.rdata <= hpmevent_rd(20); end if; - when csr_mhpmevent21_c => if (CPU_EXTENSION_RISCV_Zihpm) and (HPM_NUM_CNTS > 18) then csr.rdata <= hpmevent_rd(21); end if; - when csr_mhpmevent22_c => if (CPU_EXTENSION_RISCV_Zihpm) and (HPM_NUM_CNTS > 19) then csr.rdata <= hpmevent_rd(22); end if; - when csr_mhpmevent23_c => if (CPU_EXTENSION_RISCV_Zihpm) and (HPM_NUM_CNTS > 20) then csr.rdata <= hpmevent_rd(23); end if; - when csr_mhpmevent24_c => if (CPU_EXTENSION_RISCV_Zihpm) and (HPM_NUM_CNTS > 21) then csr.rdata <= hpmevent_rd(24); end if; - when csr_mhpmevent25_c => if (CPU_EXTENSION_RISCV_Zihpm) and (HPM_NUM_CNTS > 22) then csr.rdata <= hpmevent_rd(25); end if; - when csr_mhpmevent26_c => if (CPU_EXTENSION_RISCV_Zihpm) and (HPM_NUM_CNTS > 23) then csr.rdata <= hpmevent_rd(26); end if; - when csr_mhpmevent27_c => if (CPU_EXTENSION_RISCV_Zihpm) and (HPM_NUM_CNTS > 24) then csr.rdata <= hpmevent_rd(27); end if; - when csr_mhpmevent28_c => if (CPU_EXTENSION_RISCV_Zihpm) and (HPM_NUM_CNTS > 25) then csr.rdata <= hpmevent_rd(28); end if; - when csr_mhpmevent29_c => if (CPU_EXTENSION_RISCV_Zihpm) and (HPM_NUM_CNTS > 26) then csr.rdata <= hpmevent_rd(29); end if; - when csr_mhpmevent30_c => if (CPU_EXTENSION_RISCV_Zihpm) and (HPM_NUM_CNTS > 27) then csr.rdata <= hpmevent_rd(30); end if; - when csr_mhpmevent31_c => if (CPU_EXTENSION_RISCV_Zihpm) and (HPM_NUM_CNTS > 28) then csr.rdata <= hpmevent_rd(31); end if; + when csr_mhpmevent3_c => if (hpm_num_c > 00) then csr.rdata <= hpmevent_rd(03); end if; + when csr_mhpmevent4_c => if (hpm_num_c > 01) then csr.rdata <= hpmevent_rd(04); end if; + when csr_mhpmevent5_c => if (hpm_num_c > 02) then csr.rdata <= hpmevent_rd(05); end if; + when csr_mhpmevent6_c => if (hpm_num_c > 03) then csr.rdata <= hpmevent_rd(06); end if; + when csr_mhpmevent7_c => if (hpm_num_c > 04) then csr.rdata <= hpmevent_rd(07); end if; + when csr_mhpmevent8_c => if (hpm_num_c > 05) then csr.rdata <= hpmevent_rd(08); end if; + when csr_mhpmevent9_c => if (hpm_num_c > 06) then csr.rdata <= hpmevent_rd(09); end if; + when csr_mhpmevent10_c => if (hpm_num_c > 07) then csr.rdata <= hpmevent_rd(10); end if; + when csr_mhpmevent11_c => if (hpm_num_c > 08) then csr.rdata <= hpmevent_rd(11); end if; + when csr_mhpmevent12_c => if (hpm_num_c > 09) then csr.rdata <= hpmevent_rd(12); end if; + when csr_mhpmevent13_c => if (hpm_num_c > 10) then csr.rdata <= hpmevent_rd(13); end if; + when csr_mhpmevent14_c => if (hpm_num_c > 11) then csr.rdata <= hpmevent_rd(14); end if; + when csr_mhpmevent15_c => if (hpm_num_c > 12) then csr.rdata <= hpmevent_rd(15); end if; + when csr_mhpmevent16_c => if (hpm_num_c > 13) then csr.rdata <= hpmevent_rd(16); end if; + when csr_mhpmevent17_c => if (hpm_num_c > 14) then csr.rdata <= hpmevent_rd(17); end if; + when csr_mhpmevent18_c => if (hpm_num_c > 15) then csr.rdata <= hpmevent_rd(18); end if; + when csr_mhpmevent19_c => if (hpm_num_c > 16) then csr.rdata <= hpmevent_rd(19); end if; + when csr_mhpmevent20_c => if (hpm_num_c > 17) then csr.rdata <= hpmevent_rd(20); end if; + when csr_mhpmevent21_c => if (hpm_num_c > 18) then csr.rdata <= hpmevent_rd(21); end if; + when csr_mhpmevent22_c => if (hpm_num_c > 19) then csr.rdata <= hpmevent_rd(22); end if; + when csr_mhpmevent23_c => if (hpm_num_c > 20) then csr.rdata <= hpmevent_rd(23); end if; + when csr_mhpmevent24_c => if (hpm_num_c > 21) then csr.rdata <= hpmevent_rd(24); end if; + when csr_mhpmevent25_c => if (hpm_num_c > 22) then csr.rdata <= hpmevent_rd(25); end if; + when csr_mhpmevent26_c => if (hpm_num_c > 23) then csr.rdata <= hpmevent_rd(26); end if; + when csr_mhpmevent27_c => if (hpm_num_c > 24) then csr.rdata <= hpmevent_rd(27); end if; + when csr_mhpmevent28_c => if (hpm_num_c > 25) then csr.rdata <= hpmevent_rd(28); end if; + when csr_mhpmevent29_c => if (hpm_num_c > 26) then csr.rdata <= hpmevent_rd(29); end if; + when csr_mhpmevent30_c => if (hpm_num_c > 27) then csr.rdata <= hpmevent_rd(30); end if; + when csr_mhpmevent31_c => if (hpm_num_c > 28) then csr.rdata <= hpmevent_rd(31); end if; -- counters and timers -- -- -------------------------------------------------------------------- -- low word -- when csr_mcycle_c | csr_cycle_c => if (CPU_EXTENSION_RISCV_Zicntr) then csr.rdata <= cnt_lo_rd(00); end if; when csr_minstret_c | csr_instret_c => if (CPU_EXTENSION_RISCV_Zicntr) then csr.rdata <= cnt_lo_rd(02); end if; - when csr_mhpmcounter3_c | csr_hpmcounter3_c => if (CPU_EXTENSION_RISCV_Zihpm) and (HPM_NUM_CNTS > 00) then csr.rdata <= cnt_lo_rd(03); end if; - when csr_mhpmcounter4_c | csr_hpmcounter4_c => if (CPU_EXTENSION_RISCV_Zihpm) and (HPM_NUM_CNTS > 01) then csr.rdata <= cnt_lo_rd(04); end if; - when csr_mhpmcounter5_c | csr_hpmcounter5_c => if (CPU_EXTENSION_RISCV_Zihpm) and (HPM_NUM_CNTS > 02) then csr.rdata <= cnt_lo_rd(05); end if; - when csr_mhpmcounter6_c | csr_hpmcounter6_c => if (CPU_EXTENSION_RISCV_Zihpm) and (HPM_NUM_CNTS > 03) then csr.rdata <= cnt_lo_rd(06); end if; - when csr_mhpmcounter7_c | csr_hpmcounter7_c => if (CPU_EXTENSION_RISCV_Zihpm) and (HPM_NUM_CNTS > 04) then csr.rdata <= cnt_lo_rd(07); end if; - when csr_mhpmcounter8_c | csr_hpmcounter8_c => if (CPU_EXTENSION_RISCV_Zihpm) and (HPM_NUM_CNTS > 05) then csr.rdata <= cnt_lo_rd(08); end if; - when csr_mhpmcounter9_c | csr_hpmcounter9_c => if (CPU_EXTENSION_RISCV_Zihpm) and (HPM_NUM_CNTS > 06) then csr.rdata <= cnt_lo_rd(09); end if; - when csr_mhpmcounter10_c | csr_hpmcounter10_c => if (CPU_EXTENSION_RISCV_Zihpm) and (HPM_NUM_CNTS > 07) then csr.rdata <= cnt_lo_rd(10); end if; - when csr_mhpmcounter11_c | csr_hpmcounter11_c => if (CPU_EXTENSION_RISCV_Zihpm) and (HPM_NUM_CNTS > 08) then csr.rdata <= cnt_lo_rd(11); end if; - when csr_mhpmcounter12_c | csr_hpmcounter12_c => if (CPU_EXTENSION_RISCV_Zihpm) and (HPM_NUM_CNTS > 09) then csr.rdata <= cnt_lo_rd(12); end if; - when csr_mhpmcounter13_c | csr_hpmcounter13_c => if (CPU_EXTENSION_RISCV_Zihpm) and (HPM_NUM_CNTS > 10) then csr.rdata <= cnt_lo_rd(13); end if; - when csr_mhpmcounter14_c | csr_hpmcounter14_c => if (CPU_EXTENSION_RISCV_Zihpm) and (HPM_NUM_CNTS > 11) then csr.rdata <= cnt_lo_rd(14); end if; - when csr_mhpmcounter15_c | csr_hpmcounter15_c => if (CPU_EXTENSION_RISCV_Zihpm) and (HPM_NUM_CNTS > 12) then csr.rdata <= cnt_lo_rd(15); end if; - when csr_mhpmcounter16_c | csr_hpmcounter16_c => if (CPU_EXTENSION_RISCV_Zihpm) and (HPM_NUM_CNTS > 13) then csr.rdata <= cnt_lo_rd(16); end if; - when csr_mhpmcounter17_c | csr_hpmcounter17_c => if (CPU_EXTENSION_RISCV_Zihpm) and (HPM_NUM_CNTS > 14) then csr.rdata <= cnt_lo_rd(17); end if; - when csr_mhpmcounter18_c | csr_hpmcounter18_c => if (CPU_EXTENSION_RISCV_Zihpm) and (HPM_NUM_CNTS > 15) then csr.rdata <= cnt_lo_rd(18); end if; - when csr_mhpmcounter19_c | csr_hpmcounter19_c => if (CPU_EXTENSION_RISCV_Zihpm) and (HPM_NUM_CNTS > 16) then csr.rdata <= cnt_lo_rd(19); end if; - when csr_mhpmcounter20_c | csr_hpmcounter20_c => if (CPU_EXTENSION_RISCV_Zihpm) and (HPM_NUM_CNTS > 17) then csr.rdata <= cnt_lo_rd(20); end if; - when csr_mhpmcounter21_c | csr_hpmcounter21_c => if (CPU_EXTENSION_RISCV_Zihpm) and (HPM_NUM_CNTS > 18) then csr.rdata <= cnt_lo_rd(21); end if; - when csr_mhpmcounter22_c | csr_hpmcounter22_c => if (CPU_EXTENSION_RISCV_Zihpm) and (HPM_NUM_CNTS > 19) then csr.rdata <= cnt_lo_rd(22); end if; - when csr_mhpmcounter23_c | csr_hpmcounter23_c => if (CPU_EXTENSION_RISCV_Zihpm) and (HPM_NUM_CNTS > 20) then csr.rdata <= cnt_lo_rd(23); end if; - when csr_mhpmcounter24_c | csr_hpmcounter24_c => if (CPU_EXTENSION_RISCV_Zihpm) and (HPM_NUM_CNTS > 21) then csr.rdata <= cnt_lo_rd(24); end if; - when csr_mhpmcounter25_c | csr_hpmcounter25_c => if (CPU_EXTENSION_RISCV_Zihpm) and (HPM_NUM_CNTS > 22) then csr.rdata <= cnt_lo_rd(25); end if; - when csr_mhpmcounter26_c | csr_hpmcounter26_c => if (CPU_EXTENSION_RISCV_Zihpm) and (HPM_NUM_CNTS > 23) then csr.rdata <= cnt_lo_rd(26); end if; - when csr_mhpmcounter27_c | csr_hpmcounter27_c => if (CPU_EXTENSION_RISCV_Zihpm) and (HPM_NUM_CNTS > 24) then csr.rdata <= cnt_lo_rd(27); end if; - when csr_mhpmcounter28_c | csr_hpmcounter28_c => if (CPU_EXTENSION_RISCV_Zihpm) and (HPM_NUM_CNTS > 25) then csr.rdata <= cnt_lo_rd(28); end if; - when csr_mhpmcounter29_c | csr_hpmcounter29_c => if (CPU_EXTENSION_RISCV_Zihpm) and (HPM_NUM_CNTS > 26) then csr.rdata <= cnt_lo_rd(29); end if; - when csr_mhpmcounter30_c | csr_hpmcounter30_c => if (CPU_EXTENSION_RISCV_Zihpm) and (HPM_NUM_CNTS > 27) then csr.rdata <= cnt_lo_rd(30); end if; - when csr_mhpmcounter31_c | csr_hpmcounter31_c => if (CPU_EXTENSION_RISCV_Zihpm) and (HPM_NUM_CNTS > 28) then csr.rdata <= cnt_lo_rd(31); end if; + when csr_mhpmcounter3_c | csr_hpmcounter3_c => if (hpm_num_c > 00) then csr.rdata <= cnt_lo_rd(03); end if; + when csr_mhpmcounter4_c | csr_hpmcounter4_c => if (hpm_num_c > 01) then csr.rdata <= cnt_lo_rd(04); end if; + when csr_mhpmcounter5_c | csr_hpmcounter5_c => if (hpm_num_c > 02) then csr.rdata <= cnt_lo_rd(05); end if; + when csr_mhpmcounter6_c | csr_hpmcounter6_c => if (hpm_num_c > 03) then csr.rdata <= cnt_lo_rd(06); end if; + when csr_mhpmcounter7_c | csr_hpmcounter7_c => if (hpm_num_c > 04) then csr.rdata <= cnt_lo_rd(07); end if; + when csr_mhpmcounter8_c | csr_hpmcounter8_c => if (hpm_num_c > 05) then csr.rdata <= cnt_lo_rd(08); end if; + when csr_mhpmcounter9_c | csr_hpmcounter9_c => if (hpm_num_c > 06) then csr.rdata <= cnt_lo_rd(09); end if; + when csr_mhpmcounter10_c | csr_hpmcounter10_c => if (hpm_num_c > 07) then csr.rdata <= cnt_lo_rd(10); end if; + when csr_mhpmcounter11_c | csr_hpmcounter11_c => if (hpm_num_c > 08) then csr.rdata <= cnt_lo_rd(11); end if; + when csr_mhpmcounter12_c | csr_hpmcounter12_c => if (hpm_num_c > 09) then csr.rdata <= cnt_lo_rd(12); end if; + when csr_mhpmcounter13_c | csr_hpmcounter13_c => if (hpm_num_c > 10) then csr.rdata <= cnt_lo_rd(13); end if; + when csr_mhpmcounter14_c | csr_hpmcounter14_c => if (hpm_num_c > 11) then csr.rdata <= cnt_lo_rd(14); end if; + when csr_mhpmcounter15_c | csr_hpmcounter15_c => if (hpm_num_c > 12) then csr.rdata <= cnt_lo_rd(15); end if; + when csr_mhpmcounter16_c | csr_hpmcounter16_c => if (hpm_num_c > 13) then csr.rdata <= cnt_lo_rd(16); end if; + when csr_mhpmcounter17_c | csr_hpmcounter17_c => if (hpm_num_c > 14) then csr.rdata <= cnt_lo_rd(17); end if; + when csr_mhpmcounter18_c | csr_hpmcounter18_c => if (hpm_num_c > 15) then csr.rdata <= cnt_lo_rd(18); end if; + when csr_mhpmcounter19_c | csr_hpmcounter19_c => if (hpm_num_c > 16) then csr.rdata <= cnt_lo_rd(19); end if; + when csr_mhpmcounter20_c | csr_hpmcounter20_c => if (hpm_num_c > 17) then csr.rdata <= cnt_lo_rd(20); end if; + when csr_mhpmcounter21_c | csr_hpmcounter21_c => if (hpm_num_c > 18) then csr.rdata <= cnt_lo_rd(21); end if; + when csr_mhpmcounter22_c | csr_hpmcounter22_c => if (hpm_num_c > 19) then csr.rdata <= cnt_lo_rd(22); end if; + when csr_mhpmcounter23_c | csr_hpmcounter23_c => if (hpm_num_c > 20) then csr.rdata <= cnt_lo_rd(23); end if; + when csr_mhpmcounter24_c | csr_hpmcounter24_c => if (hpm_num_c > 21) then csr.rdata <= cnt_lo_rd(24); end if; + when csr_mhpmcounter25_c | csr_hpmcounter25_c => if (hpm_num_c > 22) then csr.rdata <= cnt_lo_rd(25); end if; + when csr_mhpmcounter26_c | csr_hpmcounter26_c => if (hpm_num_c > 23) then csr.rdata <= cnt_lo_rd(26); end if; + when csr_mhpmcounter27_c | csr_hpmcounter27_c => if (hpm_num_c > 24) then csr.rdata <= cnt_lo_rd(27); end if; + when csr_mhpmcounter28_c | csr_hpmcounter28_c => if (hpm_num_c > 25) then csr.rdata <= cnt_lo_rd(28); end if; + when csr_mhpmcounter29_c | csr_hpmcounter29_c => if (hpm_num_c > 26) then csr.rdata <= cnt_lo_rd(29); end if; + when csr_mhpmcounter30_c | csr_hpmcounter30_c => if (hpm_num_c > 27) then csr.rdata <= cnt_lo_rd(30); end if; + when csr_mhpmcounter31_c | csr_hpmcounter31_c => if (hpm_num_c > 28) then csr.rdata <= cnt_lo_rd(31); end if; -- high word -- when csr_mcycleh_c | csr_cycleh_c => if (CPU_EXTENSION_RISCV_Zicntr) then csr.rdata <= cnt_hi_rd(00); end if; when csr_minstreth_c | csr_instreth_c => if (CPU_EXTENSION_RISCV_Zicntr) then csr.rdata <= cnt_hi_rd(02); end if; - when csr_mhpmcounter3h_c | csr_hpmcounter3h_c => if (CPU_EXTENSION_RISCV_Zihpm) and (HPM_NUM_CNTS > 00) then csr.rdata <= cnt_hi_rd(03); end if; - when csr_mhpmcounter4h_c | csr_hpmcounter4h_c => if (CPU_EXTENSION_RISCV_Zihpm) and (HPM_NUM_CNTS > 01) then csr.rdata <= cnt_hi_rd(04); end if; - when csr_mhpmcounter5h_c | csr_hpmcounter5h_c => if (CPU_EXTENSION_RISCV_Zihpm) and (HPM_NUM_CNTS > 02) then csr.rdata <= cnt_hi_rd(05); end if; - when csr_mhpmcounter6h_c | csr_hpmcounter6h_c => if (CPU_EXTENSION_RISCV_Zihpm) and (HPM_NUM_CNTS > 03) then csr.rdata <= cnt_hi_rd(06); end if; - when csr_mhpmcounter7h_c | csr_hpmcounter7h_c => if (CPU_EXTENSION_RISCV_Zihpm) and (HPM_NUM_CNTS > 04) then csr.rdata <= cnt_hi_rd(07); end if; - when csr_mhpmcounter8h_c | csr_hpmcounter8h_c => if (CPU_EXTENSION_RISCV_Zihpm) and (HPM_NUM_CNTS > 05) then csr.rdata <= cnt_hi_rd(08); end if; - when csr_mhpmcounter9h_c | csr_hpmcounter9h_c => if (CPU_EXTENSION_RISCV_Zihpm) and (HPM_NUM_CNTS > 06) then csr.rdata <= cnt_hi_rd(09); end if; - when csr_mhpmcounter10h_c | csr_hpmcounter10h_c => if (CPU_EXTENSION_RISCV_Zihpm) and (HPM_NUM_CNTS > 07) then csr.rdata <= cnt_hi_rd(10); end if; - when csr_mhpmcounter11h_c | csr_hpmcounter11h_c => if (CPU_EXTENSION_RISCV_Zihpm) and (HPM_NUM_CNTS > 08) then csr.rdata <= cnt_hi_rd(11); end if; - when csr_mhpmcounter12h_c | csr_hpmcounter12h_c => if (CPU_EXTENSION_RISCV_Zihpm) and (HPM_NUM_CNTS > 09) then csr.rdata <= cnt_hi_rd(12); end if; - when csr_mhpmcounter13h_c | csr_hpmcounter13h_c => if (CPU_EXTENSION_RISCV_Zihpm) and (HPM_NUM_CNTS > 10) then csr.rdata <= cnt_hi_rd(13); end if; - when csr_mhpmcounter14h_c | csr_hpmcounter14h_c => if (CPU_EXTENSION_RISCV_Zihpm) and (HPM_NUM_CNTS > 11) then csr.rdata <= cnt_hi_rd(14); end if; - when csr_mhpmcounter15h_c | csr_hpmcounter15h_c => if (CPU_EXTENSION_RISCV_Zihpm) and (HPM_NUM_CNTS > 12) then csr.rdata <= cnt_hi_rd(15); end if; - when csr_mhpmcounter16h_c | csr_hpmcounter16h_c => if (CPU_EXTENSION_RISCV_Zihpm) and (HPM_NUM_CNTS > 13) then csr.rdata <= cnt_hi_rd(16); end if; - when csr_mhpmcounter17h_c | csr_hpmcounter17h_c => if (CPU_EXTENSION_RISCV_Zihpm) and (HPM_NUM_CNTS > 14) then csr.rdata <= cnt_hi_rd(17); end if; - when csr_mhpmcounter18h_c | csr_hpmcounter18h_c => if (CPU_EXTENSION_RISCV_Zihpm) and (HPM_NUM_CNTS > 15) then csr.rdata <= cnt_hi_rd(18); end if; - when csr_mhpmcounter19h_c | csr_hpmcounter19h_c => if (CPU_EXTENSION_RISCV_Zihpm) and (HPM_NUM_CNTS > 16) then csr.rdata <= cnt_hi_rd(19); end if; - when csr_mhpmcounter20h_c | csr_hpmcounter20h_c => if (CPU_EXTENSION_RISCV_Zihpm) and (HPM_NUM_CNTS > 17) then csr.rdata <= cnt_hi_rd(20); end if; - when csr_mhpmcounter21h_c | csr_hpmcounter21h_c => if (CPU_EXTENSION_RISCV_Zihpm) and (HPM_NUM_CNTS > 18) then csr.rdata <= cnt_hi_rd(21); end if; - when csr_mhpmcounter22h_c | csr_hpmcounter22h_c => if (CPU_EXTENSION_RISCV_Zihpm) and (HPM_NUM_CNTS > 19) then csr.rdata <= cnt_hi_rd(22); end if; - when csr_mhpmcounter23h_c | csr_hpmcounter23h_c => if (CPU_EXTENSION_RISCV_Zihpm) and (HPM_NUM_CNTS > 20) then csr.rdata <= cnt_hi_rd(23); end if; - when csr_mhpmcounter24h_c | csr_hpmcounter24h_c => if (CPU_EXTENSION_RISCV_Zihpm) and (HPM_NUM_CNTS > 21) then csr.rdata <= cnt_hi_rd(24); end if; - when csr_mhpmcounter25h_c | csr_hpmcounter25h_c => if (CPU_EXTENSION_RISCV_Zihpm) and (HPM_NUM_CNTS > 22) then csr.rdata <= cnt_hi_rd(25); end if; - when csr_mhpmcounter26h_c | csr_hpmcounter26h_c => if (CPU_EXTENSION_RISCV_Zihpm) and (HPM_NUM_CNTS > 23) then csr.rdata <= cnt_hi_rd(26); end if; - when csr_mhpmcounter27h_c | csr_hpmcounter27h_c => if (CPU_EXTENSION_RISCV_Zihpm) and (HPM_NUM_CNTS > 24) then csr.rdata <= cnt_hi_rd(27); end if; - when csr_mhpmcounter28h_c | csr_hpmcounter28h_c => if (CPU_EXTENSION_RISCV_Zihpm) and (HPM_NUM_CNTS > 25) then csr.rdata <= cnt_hi_rd(28); end if; - when csr_mhpmcounter29h_c | csr_hpmcounter29h_c => if (CPU_EXTENSION_RISCV_Zihpm) and (HPM_NUM_CNTS > 26) then csr.rdata <= cnt_hi_rd(29); end if; - when csr_mhpmcounter30h_c | csr_hpmcounter30h_c => if (CPU_EXTENSION_RISCV_Zihpm) and (HPM_NUM_CNTS > 27) then csr.rdata <= cnt_hi_rd(30); end if; - when csr_mhpmcounter31h_c | csr_hpmcounter31h_c => if (CPU_EXTENSION_RISCV_Zihpm) and (HPM_NUM_CNTS > 28) then csr.rdata <= cnt_hi_rd(31); end if; + when csr_mhpmcounter3h_c | csr_hpmcounter3h_c => if (hpm_num_c > 00) then csr.rdata <= cnt_hi_rd(03); end if; + when csr_mhpmcounter4h_c | csr_hpmcounter4h_c => if (hpm_num_c > 01) then csr.rdata <= cnt_hi_rd(04); end if; + when csr_mhpmcounter5h_c | csr_hpmcounter5h_c => if (hpm_num_c > 02) then csr.rdata <= cnt_hi_rd(05); end if; + when csr_mhpmcounter6h_c | csr_hpmcounter6h_c => if (hpm_num_c > 03) then csr.rdata <= cnt_hi_rd(06); end if; + when csr_mhpmcounter7h_c | csr_hpmcounter7h_c => if (hpm_num_c > 04) then csr.rdata <= cnt_hi_rd(07); end if; + when csr_mhpmcounter8h_c | csr_hpmcounter8h_c => if (hpm_num_c > 05) then csr.rdata <= cnt_hi_rd(08); end if; + when csr_mhpmcounter9h_c | csr_hpmcounter9h_c => if (hpm_num_c > 06) then csr.rdata <= cnt_hi_rd(09); end if; + when csr_mhpmcounter10h_c | csr_hpmcounter10h_c => if (hpm_num_c > 07) then csr.rdata <= cnt_hi_rd(10); end if; + when csr_mhpmcounter11h_c | csr_hpmcounter11h_c => if (hpm_num_c > 08) then csr.rdata <= cnt_hi_rd(11); end if; + when csr_mhpmcounter12h_c | csr_hpmcounter12h_c => if (hpm_num_c > 09) then csr.rdata <= cnt_hi_rd(12); end if; + when csr_mhpmcounter13h_c | csr_hpmcounter13h_c => if (hpm_num_c > 10) then csr.rdata <= cnt_hi_rd(13); end if; + when csr_mhpmcounter14h_c | csr_hpmcounter14h_c => if (hpm_num_c > 11) then csr.rdata <= cnt_hi_rd(14); end if; + when csr_mhpmcounter15h_c | csr_hpmcounter15h_c => if (hpm_num_c > 12) then csr.rdata <= cnt_hi_rd(15); end if; + when csr_mhpmcounter16h_c | csr_hpmcounter16h_c => if (hpm_num_c > 13) then csr.rdata <= cnt_hi_rd(16); end if; + when csr_mhpmcounter17h_c | csr_hpmcounter17h_c => if (hpm_num_c > 14) then csr.rdata <= cnt_hi_rd(17); end if; + when csr_mhpmcounter18h_c | csr_hpmcounter18h_c => if (hpm_num_c > 15) then csr.rdata <= cnt_hi_rd(18); end if; + when csr_mhpmcounter19h_c | csr_hpmcounter19h_c => if (hpm_num_c > 16) then csr.rdata <= cnt_hi_rd(19); end if; + when csr_mhpmcounter20h_c | csr_hpmcounter20h_c => if (hpm_num_c > 17) then csr.rdata <= cnt_hi_rd(20); end if; + when csr_mhpmcounter21h_c | csr_hpmcounter21h_c => if (hpm_num_c > 18) then csr.rdata <= cnt_hi_rd(21); end if; + when csr_mhpmcounter22h_c | csr_hpmcounter22h_c => if (hpm_num_c > 19) then csr.rdata <= cnt_hi_rd(22); end if; + when csr_mhpmcounter23h_c | csr_hpmcounter23h_c => if (hpm_num_c > 20) then csr.rdata <= cnt_hi_rd(23); end if; + when csr_mhpmcounter24h_c | csr_hpmcounter24h_c => if (hpm_num_c > 21) then csr.rdata <= cnt_hi_rd(24); end if; + when csr_mhpmcounter25h_c | csr_hpmcounter25h_c => if (hpm_num_c > 22) then csr.rdata <= cnt_hi_rd(25); end if; + when csr_mhpmcounter26h_c | csr_hpmcounter26h_c => if (hpm_num_c > 23) then csr.rdata <= cnt_hi_rd(26); end if; + when csr_mhpmcounter27h_c | csr_hpmcounter27h_c => if (hpm_num_c > 24) then csr.rdata <= cnt_hi_rd(27); end if; + when csr_mhpmcounter28h_c | csr_hpmcounter28h_c => if (hpm_num_c > 25) then csr.rdata <= cnt_hi_rd(28); end if; + when csr_mhpmcounter29h_c | csr_hpmcounter29h_c => if (hpm_num_c > 26) then csr.rdata <= cnt_hi_rd(29); end if; + when csr_mhpmcounter30h_c | csr_hpmcounter30h_c => if (hpm_num_c > 27) then csr.rdata <= cnt_hi_rd(30); end if; + when csr_mhpmcounter31h_c | csr_hpmcounter31h_c => if (hpm_num_c > 28) then csr.rdata <= cnt_hi_rd(31); end if; -- machine information registers -- -- -------------------------------------------------------------------- @@ -2398,11 +2422,12 @@ begin end if; end process cnt_we; + -- hardware counters -- cpu_counter_gen: for i in 0 to 31 generate -- counter CSRs -- - cnt_regs: process(rstn_i, clk_i) + cnt_reg: process(rstn_i, clk_i) begin if (rstn_i = '0') then cnt.lo(i) <= (others => '0'); @@ -2423,13 +2448,13 @@ begin cnt.hi(i) <= std_ulogic_vector(unsigned(cnt.hi(i)) + unsigned(cnt.ovf(i))); end if; end if; - end process cnt_regs; + end process cnt_reg; -- low-word increment -- - cnt.nxt(i) <= std_ulogic_vector(unsigned('0' & cnt.lo(i)) + 1) when (cnt.inc(i) = '1') else - std_ulogic_vector(unsigned('0' & cnt.lo(i)) + 0); + cnt.nxt(i) <= std_ulogic_vector(unsigned('0' & cnt.lo(i)) + 1) when (cnt.inc(i) = '1') else std_ulogic_vector(unsigned('0' & cnt.lo(i)) + 0); end generate; + -- counter CSR read-back -- cnt_connect: process(cnt) begin @@ -2444,11 +2469,11 @@ begin end if; -- hpm counters -- if (CPU_EXTENSION_RISCV_Zihpm = true) then - for i in 0 to HPM_NUM_CNTS-1 loop - if (hpm_cnt_lo_width_c > 0) then + for i in 0 to hpm_num_c-1 loop + if (hpm_cnt_lo_width_c > 0) then -- constrain low word size cnt_lo_rd(3+i)(hpm_cnt_lo_width_c-1 downto 0) <= cnt.lo(3+i)(hpm_cnt_lo_width_c-1 downto 0); end if; - if (hpm_cnt_hi_width_c > 0) then + if (hpm_cnt_hi_width_c > 0) then -- constrain high word size cnt_hi_rd(3+i)(hpm_cnt_hi_width_c-1 downto 0) <= cnt.hi(3+i)(hpm_cnt_hi_width_c-1 downto 0); end if; end loop; @@ -2467,7 +2492,7 @@ begin cnt.inc(0) <= cnt_event(hpmcnt_event_cy_c) and (not csr.mcountinhibit(0)) and (not debug_ctrl.running); -- cycle cnt.inc(2) <= cnt_event(hpmcnt_event_ir_c) and (not csr.mcountinhibit(2)) and (not debug_ctrl.running); -- instret -- HPM counters -- - for i in 0 to HPM_NUM_CNTS-1 loop + for i in 0 to hpm_num_c-1 loop cnt.inc(3+i) <= or_reduce_f(cnt_event and hpmevent.cfg(i)) and (not csr.mcountinhibit(3+i)) and (not debug_ctrl.running); end loop; end if; diff --git a/rtl/core/neorv32_cpu_regfile.vhd b/rtl/core/neorv32_cpu_regfile.vhd index 273061b10..9838c65ba 100644 --- a/rtl/core/neorv32_cpu_regfile.vhd +++ b/rtl/core/neorv32_cpu_regfile.vhd @@ -67,23 +67,24 @@ entity neorv32_cpu_regfile is csr_i : in std_ulogic_vector(XLEN-1 downto 0); -- CSR read data pc2_i : in std_ulogic_vector(XLEN-1 downto 0); -- next PC -- data output -- - rs1_o : out std_ulogic_vector(XLEN-1 downto 0); -- operand 1 - rs2_o : out std_ulogic_vector(XLEN-1 downto 0); -- operand 2 - rs3_o : out std_ulogic_vector(XLEN-1 downto 0); -- operand 4 - rs4_o : out std_ulogic_vector(XLEN-1 downto 0) -- operand 3 + rs1_o : out std_ulogic_vector(XLEN-1 downto 0); -- rs1 + rs2_o : out std_ulogic_vector(XLEN-1 downto 0); -- rs2 + rs3_o : out std_ulogic_vector(XLEN-1 downto 0); -- rs3 + rs4_o : out std_ulogic_vector(XLEN-1 downto 0) -- rs4 ); end neorv32_cpu_regfile; architecture neorv32_cpu_regfile_rtl of neorv32_cpu_regfile is + -- auto-configuration -- + constant addr_bits_c : natural := cond_sel_natural_f(RVE, 4, 5); -- address width + -- register file -- - type reg_file_t is array (31 downto 0) of std_ulogic_vector(XLEN-1 downto 0); - type reg_file_emb_t is array (15 downto 0) of std_ulogic_vector(XLEN-1 downto 0); - signal reg_file : reg_file_t; - signal reg_file_emb : reg_file_emb_t; + type reg_file_t is array ((2**addr_bits_c)-1 downto 0) of std_ulogic_vector(XLEN-1 downto 0); + signal reg_file : reg_file_t; -- access -- - signal rf_wdata : std_ulogic_vector(XLEN-1 downto 0); -- actual write-back data + signal rf_wdata : std_ulogic_vector(XLEN-1 downto 0); -- write-back data signal rf_we : std_ulogic; -- write enable signal rd_zero : std_ulogic; -- writing to x0? signal opa_addr : std_ulogic_vector(4 downto 0); -- rs1/dst address @@ -101,7 +102,7 @@ begin when rf_mux_alu_c => rf_wdata <= alu_i; -- ALU result when rf_mux_mem_c => rf_wdata <= mem_i; -- memory read data when rf_mux_csr_c => rf_wdata <= csr_i; -- CSR read data - when rf_mux_npc_c => rf_wdata <= pc2_i; -- next PC (branch return/link address) + when rf_mux_npc_c => rf_wdata <= pc2_i; -- next PC (return/link address) when others => rf_wdata <= alu_i; -- don't care end case; end process wb_select; @@ -122,66 +123,32 @@ begin rf_we <= (ctrl_i.rf_wb_en and (not rd_zero)) or ctrl_i.rf_zero_we; -- do not write to x0 unless explicitly forced - -- RV32I Register File with 32 Entries ---------------------------------------------------- + -- Register File -------------------------------------------------------------------------- -- ------------------------------------------------------------------------------------------- - reg_file_rv32i: - if (RVE = false) generate - rf_access: process(clk_i) - begin - if rising_edge(clk_i) then -- sync read and write - if (rf_we = '1') then - reg_file(to_integer(unsigned(opa_addr(4 downto 0)))) <= rf_wdata; - end if; - rs1_o <= reg_file(to_integer(unsigned(opa_addr(4 downto 0)))); - rs2_o <= reg_file(to_integer(unsigned(opb_addr(4 downto 0)))); - - -- optional 3rd read port -- - if (RS3_EN = true) then - rs3_o <= reg_file(to_integer(unsigned(opc_addr(4 downto 0)))); - else - rs3_o <= (others => '0'); - end if; - - -- optional 4th read port -- - if (RS4_EN = true) then - rs4_o <= reg_file(to_integer(unsigned(opd_addr(4 downto 0)))); - else - rs4_o <= (others => '0'); - end if; + register_file: process(clk_i) + begin + if rising_edge(clk_i) then + if (rf_we = '1') then + reg_file(to_integer(unsigned(opa_addr(addr_bits_c-1 downto 0)))) <= rf_wdata; + end if; + rs1_o <= reg_file(to_integer(unsigned(opa_addr(addr_bits_c-1 downto 0)))); + rs2_o <= reg_file(to_integer(unsigned(opb_addr(addr_bits_c-1 downto 0)))); + + -- optional 3rd read port -- + if (RS3_EN = true) then + rs3_o <= reg_file(to_integer(unsigned(opc_addr(addr_bits_c-1 downto 0)))); + else + rs3_o <= (others => '0'); end if; - end process rf_access; - end generate; - - -- RV32E Register File with 16 Entries ---------------------------------------------------- - -- ------------------------------------------------------------------------------------------- - reg_file_rv32e: - if (RVE = true) generate - rf_access: process(clk_i) - begin - if rising_edge(clk_i) then -- sync read and write - if (rf_we = '1') then - reg_file_emb(to_integer(unsigned(opa_addr(3 downto 0)))) <= rf_wdata; - end if; - rs1_o <= reg_file_emb(to_integer(unsigned(opa_addr(3 downto 0)))); - rs2_o <= reg_file_emb(to_integer(unsigned(opb_addr(3 downto 0)))); - - -- optional 3rd read port -- - if (RS3_EN = true) then - rs3_o <= reg_file_emb(to_integer(unsigned(opc_addr(3 downto 0)))); - else - rs3_o <= (others => '0'); - end if; - - -- optional 4th read port -- - if (RS4_EN = true) then -- implement fourth read port? - rs4_o <= reg_file_emb(to_integer(unsigned(opd_addr(3 downto 0)))); - else - rs4_o <= (others => '0'); - end if; + -- optional 4th read port -- + if (RS4_EN = true) then + rs4_o <= reg_file(to_integer(unsigned(opd_addr(addr_bits_c-1 downto 0)))); + else + rs4_o <= (others => '0'); end if; - end process rf_access; - end generate; + end if; + end process register_file; end neorv32_cpu_regfile_rtl; diff --git a/rtl/core/neorv32_intercon.vhd b/rtl/core/neorv32_intercon.vhd index c1a4d0bef..e0e97bca0 100644 --- a/rtl/core/neorv32_intercon.vhd +++ b/rtl/core/neorv32_intercon.vhd @@ -1,8 +1,8 @@ -- ################################################################################################# --- # << NEORV32 - Processor Bus: 2-to-1 Bus Switch >> # +-- # << NEORV32 - Processor Bus Infrastructure: 2-to-1 Bus Switch >> # -- # ********************************************************************************************* # --- # Allows to access a single bus ("p_bus") by two controller ports. Controller port A ("ca_bus") # --- # has priority over controller port B ("cb_bus"). # +-- # Allows to access a single device bus X by two controller ports A and B. # +-- # Controller port A has priority over controller port B. # -- # ********************************************************************************************* # -- # BSD 3-Clause License # -- # # @@ -42,7 +42,7 @@ use ieee.numeric_std.all; library neorv32; use neorv32.neorv32_package.all; -entity neorv32_busswitch is +entity neorv32_bus_switch is generic ( PORT_A_READ_ONLY : boolean; -- set if port A is read-only PORT_B_READ_ONLY : boolean -- set if port B is read-only @@ -57,9 +57,9 @@ entity neorv32_busswitch is x_req_o : out bus_req_t; -- device port request bus x_rsp_i : in bus_rsp_t -- device port response bus ); -end neorv32_busswitch; +end neorv32_bus_switch; -architecture neorv32_busswitch_rtl of neorv32_busswitch is +architecture neorv32_bus_switch_rtl of neorv32_bus_switch is -- access requests -- signal a_rd_req_buf, a_wr_req_buf : std_ulogic; @@ -68,16 +68,16 @@ architecture neorv32_busswitch_rtl of neorv32_busswitch is signal b_req_current, b_req_pending : std_ulogic; -- internal bus lines -- - signal a_bus_ack, b_bus_ack : std_ulogic; - signal a_bus_err, b_bus_err : std_ulogic; - signal x_bus_we, x_bus_re : std_ulogic; + signal a_bus_ack, a_bus_err : std_ulogic; + signal b_bus_ack, b_bus_err : std_ulogic; + signal x_bus_we, x_bus_re : std_ulogic; -- access arbiter -- - type arbiter_state_t is (IDLE, A_BUSY, A_RETIRE, B_BUSY, B_RETIRE); + type arbiter_state_t is (IDLE, BUSY_A, BUSY_B); type arbiter_t is record state : arbiter_state_t; state_nxt : arbiter_state_t; - bus_sel : std_ulogic; + host_sel : std_ulogic; re_trig : std_ulogic; we_trig : std_ulogic; end record; @@ -91,18 +91,16 @@ begin begin if (rstn_i = '0') then arbiter.state <= IDLE; - a_rd_req_buf <= '0'; - a_wr_req_buf <= '0'; - b_rd_req_buf <= '0'; - b_wr_req_buf <= '0'; + a_rd_req_buf <= '0'; + a_wr_req_buf <= '0'; + b_rd_req_buf <= '0'; + b_wr_req_buf <= '0'; elsif rising_edge(clk_i) then arbiter.state <= arbiter.state_nxt; - -- port A requests -- - a_rd_req_buf <= (a_rd_req_buf or a_req_i.re) and (not (a_bus_err or a_bus_ack)); - a_wr_req_buf <= (a_wr_req_buf or a_req_i.we) and (not (a_bus_err or a_bus_ack)) and bool_to_ulogic_f(PORT_A_READ_ONLY = false); - -- port B requests -- - b_rd_req_buf <= (b_rd_req_buf or b_req_i.re) and (not (b_bus_err or b_bus_ack)); - b_wr_req_buf <= (b_wr_req_buf or b_req_i.we) and (not (b_bus_err or b_bus_ack)) and bool_to_ulogic_f(PORT_B_READ_ONLY = false); + a_rd_req_buf <= (a_rd_req_buf or a_req_i.re) and (not (a_bus_err or a_bus_ack)); + a_wr_req_buf <= (a_wr_req_buf or a_req_i.we) and (not (a_bus_err or a_bus_ack)) and bool_to_ulogic_f(not PORT_A_READ_ONLY); + b_rd_req_buf <= (b_rd_req_buf or b_req_i.re) and (not (b_bus_err or b_bus_ack)); + b_wr_req_buf <= (b_wr_req_buf or b_req_i.we) and (not (b_bus_err or b_bus_ack)) and bool_to_ulogic_f(not PORT_B_READ_ONLY); end if; end process arbiter_sync; @@ -114,13 +112,14 @@ begin a_req_pending <= (a_rd_req_buf or a_wr_req_buf) when (PORT_A_READ_ONLY = false) else a_rd_req_buf; b_req_pending <= (b_rd_req_buf or b_wr_req_buf) when (PORT_B_READ_ONLY = false) else b_rd_req_buf; + -- FSM -- arbiter_comb: process(arbiter, a_req_current, b_req_current, a_req_pending, b_req_pending, a_rd_req_buf, a_wr_req_buf, b_rd_req_buf, b_wr_req_buf, x_rsp_i) begin -- arbiter defaults -- arbiter.state_nxt <= arbiter.state; - arbiter.bus_sel <= '0'; + arbiter.host_sel <= '0'; arbiter.we_trig <= '0'; arbiter.re_trig <= '0'; @@ -129,57 +128,32 @@ begin when IDLE => -- wait for requests -- ------------------------------------------------------------ - if (a_req_current = '1') then -- current request from port A? - arbiter.bus_sel <= '0'; - arbiter.state_nxt <= A_BUSY; - elsif (a_req_pending = '1') then -- pending request from port A? - arbiter.bus_sel <= '0'; - arbiter.state_nxt <= A_RETIRE; - elsif (b_req_current = '1') then -- pending request from port B? - arbiter.bus_sel <= '1'; - arbiter.state_nxt <= B_BUSY; - elsif (b_req_pending = '1') then -- current request from port B? - arbiter.bus_sel <= '1'; - arbiter.state_nxt <= B_RETIRE; + if (a_req_current = '1') or (a_req_pending = '1') then -- any request from port A? + arbiter.host_sel <= '0'; + arbiter.we_trig <= a_wr_req_buf; + arbiter.re_trig <= a_rd_req_buf; + arbiter.state_nxt <= BUSY_A; + elsif (b_req_current = '1') or (b_req_pending = '1') then -- any request from port B? + arbiter.host_sel <= '1'; + arbiter.we_trig <= b_wr_req_buf; + arbiter.re_trig <= b_rd_req_buf; + arbiter.state_nxt <= BUSY_B; end if; - when A_BUSY => -- port A pending access + when BUSY_A => -- port A access in progress -- ------------------------------------------------------------ - arbiter.bus_sel <= '0'; -- access from port A + arbiter.host_sel <= '0'; if (x_rsp_i.err = '1') or (x_rsp_i.ack = '1') then --- [NOTE] Directly return to IDLE state to further promote port A access requests. --- if (b_req_pending = '1') or (b_req_current = '1') then -- any request from B? --- arbiter.state_nxt <= B_RETIRE; --- else - arbiter.state_nxt <= IDLE; --- end if; + arbiter.state_nxt <= IDLE; end if; - when A_RETIRE => -- retire port A pending access - -- ------------------------------------------------------------ - arbiter.bus_sel <= '0'; -- access from port A - arbiter.we_trig <= a_wr_req_buf; - arbiter.re_trig <= a_rd_req_buf; - arbiter.state_nxt <= A_BUSY; - - when B_BUSY => -- port B pending access + when BUSY_B => -- port B access in progress -- ------------------------------------------------------------ - arbiter.bus_sel <= '1'; -- access from port B + arbiter.host_sel <= '1'; if (x_rsp_i.err = '1') or (x_rsp_i.ack = '1') then - if (a_req_pending = '1') or (a_req_current = '1') then -- any request from A? - arbiter.state_nxt <= A_RETIRE; - else - arbiter.state_nxt <= IDLE; - end if; + arbiter.state_nxt <= IDLE; end if; - when B_RETIRE => -- retire port B pending access - -- ------------------------------------------------------------ - arbiter.bus_sel <= '1'; -- access from port B - arbiter.we_trig <= b_wr_req_buf; - arbiter.re_trig <= b_rd_req_buf; - arbiter.state_nxt <= B_BUSY; - when others => -- undefined -- ------------------------------------------------------------ arbiter.state_nxt <= IDLE; @@ -188,42 +162,45 @@ begin end process arbiter_comb; - -- Peripheral Bus Switch ------------------------------------------------------------------ + -- Device Request Switch ------------------------------------------------------------------ -- ------------------------------------------------------------------------------------------- - x_req_o.addr <= a_req_i.addr when (arbiter.bus_sel = '0') else b_req_i.addr; + x_req_o.addr <= a_req_i.addr when (arbiter.host_sel = '0') else b_req_i.addr; x_req_o.data <= b_req_i.data when (PORT_A_READ_ONLY = true) else a_req_i.data when (PORT_B_READ_ONLY = true) else - a_req_i.data when (arbiter.bus_sel = '0') else b_req_i.data; + a_req_i.data when (arbiter.host_sel = '0') else b_req_i.data; x_req_o.ben <= b_req_i.ben when (PORT_A_READ_ONLY = true) else a_req_i.ben when (PORT_B_READ_ONLY = true) else - a_req_i.ben when (arbiter.bus_sel = '0') else b_req_i.ben; + a_req_i.ben when (arbiter.host_sel = '0') else b_req_i.ben; - x_req_o.priv <= a_req_i.priv when (arbiter.bus_sel = '0') else b_req_i.priv; - x_req_o.src <= a_req_i.src when (arbiter.bus_sel = '0') else b_req_i.src; - x_req_o.rvso <= a_req_i.rvso when (arbiter.bus_sel = '0') else b_req_i.rvso; + x_req_o.rvso <= a_req_i.rvso when (arbiter.host_sel = '0') else b_req_i.rvso; + x_req_o.priv <= a_req_i.priv when (arbiter.host_sel = '0') else b_req_i.priv; + x_req_o.src <= a_req_i.src when (arbiter.host_sel = '0') else b_req_i.src; - x_bus_we <= a_req_i.we when (arbiter.bus_sel = '0') else b_req_i.we; - x_bus_re <= a_req_i.re when (arbiter.bus_sel = '0') else b_req_i.re; + x_bus_we <= a_req_i.we when (arbiter.host_sel = '0') else b_req_i.we; + x_bus_re <= a_req_i.re when (arbiter.host_sel = '0') else b_req_i.re; x_req_o.we <= x_bus_we or arbiter.we_trig; x_req_o.re <= x_bus_re or arbiter.re_trig; + + -- Device Response Switch ----------------------------------------------------------------- + -- ------------------------------------------------------------------------------------------- a_rsp_o.data <= x_rsp_i.data; b_rsp_o.data <= x_rsp_i.data; - a_bus_ack <= x_rsp_i.ack when (arbiter.bus_sel = '0') else '0'; - b_bus_ack <= x_rsp_i.ack when (arbiter.bus_sel = '1') else '0'; + a_bus_ack <= x_rsp_i.ack when (arbiter.host_sel = '0') else '0'; + b_bus_ack <= x_rsp_i.ack when (arbiter.host_sel = '1') else '0'; a_rsp_o.ack <= a_bus_ack; b_rsp_o.ack <= b_bus_ack; - a_bus_err <= x_rsp_i.err when (arbiter.bus_sel = '0') else '0'; - b_bus_err <= x_rsp_i.err when (arbiter.bus_sel = '1') else '0'; + a_bus_err <= x_rsp_i.err when (arbiter.host_sel = '0') else '0'; + b_bus_err <= x_rsp_i.err when (arbiter.host_sel = '1') else '0'; a_rsp_o.err <= a_bus_err; b_rsp_o.err <= b_bus_err; -end neorv32_busswitch_rtl; +end neorv32_bus_switch_rtl; -- ############################################################################################################################ @@ -231,7 +208,7 @@ end neorv32_busswitch_rtl; -- ################################################################################################# --- # << NEORV32 - Processor Bus: Section Gateway >> # +-- # << NEORV32 - Processor Bus Infrastructure: Section Gateway >> # -- # ********************************************************************************************* # -- # Bus gateway to distribute the core's access to the processor's main memory sections: # -- # -> IMEM - internal instruction memory [optional], {rwx} # @@ -282,7 +259,7 @@ use ieee.numeric_std.all; library neorv32; use neorv32.neorv32_package.all; -entity neorv32_gateway is +entity neorv32_bus_gateway is generic ( TIMEOUT : natural; -- internal bus timeout cycles -- IMEM port -- @@ -303,8 +280,6 @@ entity neorv32_gateway is BOOT_SIZE : natural; -- IO port -- IO_ENABLE : boolean; - IO_REQ_REG : boolean; - IO_RSP_REG : boolean; IO_BASE : std_ulogic_vector(31 downto 0); IO_SIZE : natural; -- EXTERNAL port -- @@ -331,9 +306,9 @@ entity neorv32_gateway is ext_req_o : out bus_req_t; ext_rsp_i : in bus_rsp_t ); -end neorv32_gateway; +end neorv32_bus_gateway; -architecture neorv32_gateway_rtl of neorv32_gateway is +architecture neorv32_bus_gateway_rtl of neorv32_bus_gateway is -- port select -- constant port_imem_c : natural := 0; @@ -344,10 +319,6 @@ architecture neorv32_gateway_rtl of neorv32_gateway is constant port_ext_c : natural := 5; signal port_sel : std_ulogic_vector(5 downto 0); - -- IO buffer stage -- - signal io_req : bus_req_t; - signal io_rsp : bus_rsp_t; - -- response summary -- signal int_rsp : bus_rsp_t; @@ -398,9 +369,9 @@ begin dmem_req_o <= req_terminate_c; end if; if (XIP_ENABLE = true) then - xip_req_o <= main_req_i; - xip_req_o.we <= '0'; -- PMA: read-only - xip_req_o.re <= main_req_i.re and port_sel(port_xip_c); + xip_req_o <= main_req_i; + xip_req_o.we <= '0'; -- PMA: read-only + xip_req_o.re <= main_req_i.re and port_sel(port_xip_c); else xip_req_o <= req_terminate_c; end if; @@ -412,62 +383,25 @@ begin boot_req_o <= req_terminate_c; end if; if (IO_ENABLE = true) then - io_req <= main_req_i; - io_req.we <= main_req_i.we and port_sel(port_io_c); - io_req.re <= main_req_i.re and port_sel(port_io_c); + io_req_o <= main_req_i; + io_req_o.we <= main_req_i.we and port_sel(port_io_c); + io_req_o.re <= main_req_i.re and port_sel(port_io_c); else - io_req <= req_terminate_c; + io_req_o <= req_terminate_c; end if; if (EXT_ENABLE = true) then - ext_req_o <= main_req_i; - ext_req_o.we <= main_req_i.we and port_sel(port_ext_c); - ext_req_o.re <= main_req_i.re and port_sel(port_ext_c); + ext_req_o <= main_req_i; + ext_req_o.we <= main_req_i.we and port_sel(port_ext_c); + ext_req_o.re <= main_req_i.re and port_sel(port_ext_c); else ext_req_o <= req_terminate_c; end if; end process request; - -- IO Port Register Stages ---------------------------------------------------------------- - -- ------------------------------------------------------------------------------------------- - io_req_buffer_true: - if (IO_REQ_REG = true) generate - io_req_buffer: process(rstn_i, clk_i) - begin - if (rstn_i = '0') then - io_req_o <= req_terminate_c; - elsif rising_edge(clk_i) then - io_req_o <= io_req; - end if; - end process io_req_buffer; - end generate; - - io_req_buffer_false: - if (IO_REQ_REG = false) generate - io_req_o <= io_req; - end generate; - - io_rsp_buffer_true: - if (IO_RSP_REG = true) generate - io_rsp_buffer: process(rstn_i, clk_i) - begin - if (rstn_i = '0') then - io_rsp <= rsp_terminate_c; - elsif rising_edge(clk_i) then - io_rsp <= io_rsp_i; - end if; - end process io_rsp_buffer; - end generate; - - io_rsp_buffer_false: - if (IO_RSP_REG = false) generate - io_rsp <= io_rsp_i; - end generate; - - -- Bus Response --------------------------------------------------------------------------- -- ------------------------------------------------------------------------------------------- - response: process(imem_rsp_i, dmem_rsp_i, boot_rsp_i, xip_rsp_i, io_rsp, ext_rsp_i) + response: process(imem_rsp_i, dmem_rsp_i, boot_rsp_i, xip_rsp_i, io_rsp_i, ext_rsp_i) variable tmp_v : bus_rsp_t; begin tmp_v := rsp_terminate_c; -- start will all-zero @@ -492,9 +426,9 @@ begin tmp_v.err := tmp_v.err or boot_rsp_i.err; end if; if (IO_ENABLE = true) then - tmp_v.data := tmp_v.data or io_rsp.data; - tmp_v.ack := tmp_v.ack or io_rsp.ack; - tmp_v.err := tmp_v.err or io_rsp.err; + tmp_v.data := tmp_v.data or io_rsp_i.data; + tmp_v.ack := tmp_v.ack or io_rsp_i.ack; + tmp_v.err := tmp_v.err or io_rsp_i.err; end if; if (EXT_ENABLE = true) then tmp_v.data := tmp_v.data or ext_rsp_i.data; @@ -520,8 +454,7 @@ begin keeper.err <= '0'; keeper.halt <= '0'; elsif rising_edge(clk_i) then - -- defaults -- - keeper.err <= '0'; + keeper.err <= '0'; -- default keeper.halt <= port_sel(port_xip_c) or port_sel(port_ext_c); -- no timeout if XIP or EXTERNAL access -- fsm -- if (keeper.busy = '0') then -- bus idle @@ -542,7 +475,7 @@ begin end process bus_monitor; -end neorv32_gateway_rtl; +end neorv32_bus_gateway_rtl; -- ############################################################################################################################ @@ -550,7 +483,7 @@ end neorv32_gateway_rtl; -- ################################################################################################# --- # << NEORV32 - Processor Bus: IO Switch >> # +-- # << NEORV32 - Processor Bus Infrastructure: IO Switch >> # -- # ********************************************************************************************* # -- # Simple address decoding switch for the processor's internal IO/peripheral devices. # -- # ********************************************************************************************* # @@ -592,7 +525,7 @@ use ieee.numeric_std.all; library neorv32; use neorv32.neorv32_package.all; -entity io_switch is +entity neorv32_bus_io_switch is generic ( DEV_SIZE : natural; -- size of a single IO device, has to be a power of two -- device port enable and base address -- @@ -645,9 +578,9 @@ entity io_switch is dev_19_req_o : out bus_req_t; dev_19_rsp_i : in bus_rsp_t; dev_20_req_o : out bus_req_t; dev_20_rsp_i : in bus_rsp_t ); -end io_switch; +end neorv32_bus_io_switch; -architecture io_switch_rtl of io_switch is +architecture neorv32_bus_io_switch_rtl of neorv32_bus_io_switch is -- ------------------------------------------------------------------------------------------- -- -- How to add another device port -- @@ -804,7 +737,7 @@ begin end process; -end io_switch_rtl; +end neorv32_bus_io_switch_rtl; -- ############################################################################################################################ @@ -812,7 +745,7 @@ end io_switch_rtl; -- ################################################################################################# --- # << NEORV32 - Processor Bus: Reservation Set Control >> # +-- # << NEORV32 - Processor Bus Infrastructure: Reservation Set Control >> # -- # ********************************************************************************************* # -- # Reservation set controller for the A (atomic) ISA extension's LR.W (load-reservate) and SC.W # -- # (store-conditional) instructions. Only a single reservation set is supported. # @@ -856,7 +789,7 @@ use ieee.numeric_std.all; library neorv32; use neorv32.neorv32_package.all; -entity neorv32_reservation_set is +entity neorv32_bus_reservation_set is generic ( GRANULARITY : natural -- reservation set granularity in bytes; has to be power of 2, min 4 ); @@ -875,9 +808,9 @@ entity neorv32_reservation_set is sys_req_o : out bus_req_t; sys_rsp_i : in bus_rsp_t ); -end neorv32_reservation_set; +end neorv32_bus_reservation_set; -architecture neorv32_reservation_set_rtl of neorv32_reservation_set is +architecture neorv32_bus_reservation_set_rtl of neorv32_bus_reservation_set is -- reservation set granularity address boundary bit -- constant abb_c : natural := index_size_f(GRANULARITY); @@ -998,4 +931,4 @@ begin core_rsp_o.data(0) <= sys_rsp_i.data(0) or (core_req_i.rvso and (not rsvs.valid)); -- inject 1 into read data's LSB if SC fails -end neorv32_reservation_set_rtl; +end neorv32_bus_reservation_set_rtl; diff --git a/rtl/core/neorv32_package.vhd b/rtl/core/neorv32_package.vhd index af71602dd..2d5a1f34f 100644 --- a/rtl/core/neorv32_package.vhd +++ b/rtl/core/neorv32_package.vhd @@ -54,9 +54,12 @@ package neorv32_package is -- log2 of co-processor timeout cycles -- constant cp_timeout_c : natural := 7; -- default = 7 (= 128 cycles) + -- instruction prefetch buffer depth -- + constant ipb_depth_c : natural := 2; -- hast to be a power of two, min 2, default 2 + -- Architecture Constants ----------------------------------------------------------------- -- ------------------------------------------------------------------------------------------- - constant hw_version_c : std_ulogic_vector(31 downto 0) := x"01080703"; -- hardware version + constant hw_version_c : std_ulogic_vector(31 downto 0) := x"01080704"; -- hardware version constant archid_c : natural := 19; -- official RISC-V architecture ID constant XLEN : natural := 32; -- native data path width, do not change! @@ -654,7 +657,7 @@ package neorv32_package is alu_unsigned : std_ulogic; -- is unsigned ALU operation alu_frm : std_ulogic_vector(02 downto 0); -- FPU rounding mode alu_cp_trig : std_ulogic_vector(05 downto 0); -- co-processor trigger (one-hot) - -- bus interface -- + -- data bus interface -- bus_req_rd : std_ulogic; -- trigger memory read request bus_req_wr : std_ulogic; -- trigger memory write request bus_mo_we : std_ulogic; -- memory address and data output register write enable @@ -755,10 +758,6 @@ package neorv32_package is constant trap_sma_c : std_ulogic_vector(6 downto 0) := "0" & "0" & "00110"; -- 6: store address misaligned constant trap_saf_c : std_ulogic_vector(6 downto 0) := "0" & "0" & "00111"; -- 7: store access fault constant trap_env_c : std_ulogic_vector(6 downto 0) := "0" & "0" & "010UU"; -- 8..11: environment call from u/s/h/m ---constant trap_ipf_c : std_ulogic_vector(6 downto 0) := "0" & "0" & "01100"; -- 12: instruction page fault ---constant trap_lpf_c : std_ulogic_vector(6 downto 0) := "0" & "0" & "01101"; -- 13: load page fault ---constant trap_???_c : std_ulogic_vector(6 downto 0) := "0" & "0" & "01110"; -- 14: reserved ---constant trap_spf_c : std_ulogic_vector(6 downto 0) := "0" & "0" & "01111"; -- 15: store page fault -- RISC-V compliant asynchronous exceptions (interrupts) -- constant trap_msi_c : std_ulogic_vector(6 downto 0) := "1" & "0" & "00011"; -- 3: machine software interrupt constant trap_mti_c : std_ulogic_vector(6 downto 0) := "1" & "0" & "00111"; -- 7: machine timer interrupt @@ -860,7 +859,6 @@ package neorv32_package is function index_size_f(input : natural) return natural; function cond_sel_natural_f(cond : boolean; val_t : natural; val_f : natural) return natural; - function cond_sel_int_f(cond : boolean; val_t : integer; val_f : integer) return integer; function cond_sel_suv_f(cond : boolean; val_t : std_ulogic_vector; val_f : std_ulogic_vector) return std_ulogic_vector; function cond_sel_string_f(cond : boolean; val_t : string; val_f : string) return string; function bool_to_ulogic_f(cond : boolean) return std_ulogic; @@ -908,7 +906,6 @@ package neorv32_package is -- Tuning Options -- FAST_MUL_EN : boolean := false; -- use DSPs for M extension's multiplier FAST_SHIFT_EN : boolean := false; -- use barrel shifter for shift operations - CPU_IPB_ENTRIES : natural := 1; -- entries in instruction prefetch buffer, has to be a power of 2, min 1 -- Physical Memory Protection (PMP) -- PMP_NUM_REGIONS : natural := 0; -- number of regions (0..16) PMP_MIN_GRANULARITY : natural := 4; -- minimal region granularity in bytes, has to be a power of 2, min 4 bytes @@ -1090,17 +1087,6 @@ package body neorv32_package is end if; end function cond_sel_natural_f; - -- Conditional select integer ------------------------------------------------------------- - -- ------------------------------------------------------------------------------------------- - function cond_sel_int_f(cond : boolean; val_t : integer; val_f : integer) return integer is - begin - if (cond = true) then - return val_t; - else - return val_f; - end if; - end function cond_sel_int_f; - -- Conditional select std_ulogic_vector --------------------------------------------------- -- ------------------------------------------------------------------------------------------- function cond_sel_suv_f(cond : boolean; val_t : std_ulogic_vector; val_f : std_ulogic_vector) return std_ulogic_vector is diff --git a/rtl/core/neorv32_top.vhd b/rtl/core/neorv32_top.vhd index 45632ed70..59218cf5e 100644 --- a/rtl/core/neorv32_top.vhd +++ b/rtl/core/neorv32_top.vhd @@ -73,7 +73,6 @@ entity neorv32_top is -- Tuning Options -- FAST_MUL_EN : boolean := false; -- use DSPs for M extension's multiplier FAST_SHIFT_EN : boolean := false; -- use barrel shifter for shift operations - CPU_IPB_ENTRIES : natural := 1; -- entries in instruction prefetch buffer, has to be a power of 2, min 1 -- Physical Memory Protection (PMP) -- PMP_NUM_REGIONS : natural := 0; -- number of regions (0..16) @@ -255,7 +254,6 @@ architecture neorv32_top_rtl of neorv32_top is -- auto-configuration -- constant cpu_boot_addr_c : std_ulogic_vector(31 downto 0) := cond_sel_suv_f(INT_BOOTLOADER_EN, mem_boot_base_c, mem_imem_base_c); - constant io_reg_buf_en_c : boolean := ICACHE_EN or DCACHE_EN; constant imem_as_rom_c : boolean := not INT_BOOTLOADER_EN; constant io_gpio_en_c : boolean := boolean(IO_GPIO_NUM > 0); constant io_xirq_en_c : boolean := boolean(XIRQ_NUM_CH > 0); @@ -499,7 +497,6 @@ begin -- Extension Options -- FAST_MUL_EN => FAST_MUL_EN, FAST_SHIFT_EN => FAST_SHIFT_EN, - CPU_IPB_ENTRIES => CPU_IPB_ENTRIES, -- Physical Memory Protection (PMP) -- PMP_NUM_REGIONS => PMP_NUM_REGIONS, PMP_MIN_GRANULARITY => PMP_MIN_GRANULARITY, @@ -611,7 +608,7 @@ begin -- Core Complex Bus Switch ---------------------------------------------------------------- -- ------------------------------------------------------------------------------------------- - neorv32_core_busswitch_inst: entity neorv32.neorv32_busswitch + neorv32_core_bus_switch_inst: entity neorv32.neorv32_bus_switch generic map ( PORT_A_READ_ONLY => false, PORT_B_READ_ONLY => true -- i-fetch is read-only @@ -619,7 +616,7 @@ begin port map ( clk_i => clk_i, rstn_i => rstn_int, - a_req_i => dcache_req, + a_req_i => dcache_req, -- prioritized a_rsp_o => dcache_rsp, b_req_i => icache_req, b_rsp_o => icache_rsp, @@ -653,7 +650,7 @@ begin -- DMA Bus Switch ------------------------------------------------------------------------- -- ------------------------------------------------------------------------------------------- - neorv32_dma_busswitch_inst: entity neorv32.neorv32_busswitch + neorv32_dma_bus_switch_inst: entity neorv32.neorv32_bus_switch generic map ( PORT_A_READ_ONLY => false, PORT_B_READ_ONLY => false @@ -661,7 +658,7 @@ begin port map ( clk_i => clk_i, rstn_i => rstn_int, - a_req_i => core_req, + a_req_i => core_req, -- prioritized a_rsp_o => core_rsp, b_req_i => dma_req, b_rsp_o => dma_rsp, @@ -669,7 +666,7 @@ begin x_rsp_i => main_rsp ); - end generate; + end generate; -- /neorv32_dma_complex_true neorv32_dma_complex_false: if (IO_DMA_EN = false) generate @@ -683,9 +680,9 @@ begin -- ************************************************************************************************************************** -- Reservation Set Controller (for atomic LR/SC memory accesses) -- ************************************************************************************************************************** - neorv32_reservation_set_true: + neorv32_bus_reservation_set_true: if (CPU_EXTENSION_RISCV_A = true) generate - neorv32_reservation_set_inst: entity neorv32.neorv32_reservation_set + neorv32_bus_reservation_set_inst: entity neorv32.neorv32_bus_reservation_set generic map ( GRANULARITY => AMO_RVS_GRANULARITY ) @@ -702,7 +699,7 @@ begin ); end generate; - neorv32_reservation_set_false: + neorv32_bus_reservation_set_false: if (CPU_EXTENSION_RISCV_A = false) generate main2_req <= main_req; main_rsp <= main2_rsp; @@ -712,7 +709,7 @@ begin -- ************************************************************************************************************************** -- Address Region Gateway -- ************************************************************************************************************************** - neorv32_gateway_inst: entity neorv32.neorv32_gateway + neorv32_bus_gateway_inst: entity neorv32.neorv32_bus_gateway generic map ( TIMEOUT => max_proc_int_response_time_c, -- IMEM port -- @@ -733,8 +730,6 @@ begin BOOT_SIZE => mem_boot_size_c, -- IO port -- IO_ENABLE => true, -- always enabled (mandatory core module) - IO_REQ_REG => io_reg_buf_en_c, - IO_RSP_REG => io_reg_buf_en_c, IO_BASE => mem_io_base_c, IO_SIZE => mem_io_size_c, -- EXT port -- @@ -917,7 +912,7 @@ begin -- IO Switch ------------------------------------------------------------------------------ -- ------------------------------------------------------------------------------------------- - io_switch_inst: entity neorv32.io_switch + neorv32_bus_io_switch_inst: entity neorv32.neorv32_bus_io_switch generic map ( DEV_SIZE => iodev_size_c, -- size of a single IO device -- device port enable and base address -- diff --git a/rtl/system_integration/neorv32_SystemTop_AvalonMM.vhd b/rtl/system_integration/neorv32_SystemTop_AvalonMM.vhd index 2c7af5991..ec65a47c3 100644 --- a/rtl/system_integration/neorv32_SystemTop_AvalonMM.vhd +++ b/rtl/system_integration/neorv32_SystemTop_AvalonMM.vhd @@ -69,7 +69,6 @@ entity neorv32_top_avalonmm is -- Extension Options -- FAST_MUL_EN : boolean := false; -- use DSPs for M extension's multiplier FAST_SHIFT_EN : boolean := false; -- use barrel shifter for shift operations - CPU_IPB_ENTRIES : natural := 1; -- entries is instruction prefetch buffer, has to be a power of 1, min 1 -- Physical Memory Protection (PMP) -- PMP_NUM_REGIONS : natural := 0; -- number of regions (0..16) @@ -254,7 +253,6 @@ begin -- Extension Options -- FAST_MUL_EN => FAST_MUL_EN, FAST_SHIFT_EN => FAST_SHIFT_EN, - CPU_IPB_ENTRIES => CPU_IPB_ENTRIES, -- Physical Memory Protection (PMP) -- PMP_NUM_REGIONS => PMP_NUM_REGIONS, diff --git a/rtl/system_integration/neorv32_SystemTop_axi4lite.vhd b/rtl/system_integration/neorv32_SystemTop_axi4lite.vhd index 4f4c047da..0aef226ea 100644 --- a/rtl/system_integration/neorv32_SystemTop_axi4lite.vhd +++ b/rtl/system_integration/neorv32_SystemTop_axi4lite.vhd @@ -321,7 +321,6 @@ begin -- Extension Options -- FAST_MUL_EN => FAST_MUL_EN, -- use DSPs for M extension's multiplier FAST_SHIFT_EN => FAST_SHIFT_EN, -- use barrel shifter for shift operations - CPU_IPB_ENTRIES => 2, -- entries is instruction prefetch buffer, has to be a power of 2, min 1 -- Physical Memory Protection (PMP) -- PMP_NUM_REGIONS => PMP_NUM_REGIONS, -- number of regions (0..16) PMP_MIN_GRANULARITY => PMP_MIN_GRANULARITY, -- minimal region granularity in bytes, has to be a power of 2, min 4 bytes diff --git a/rtl/system_integration/neorv32_litex_core_complex.vhd b/rtl/system_integration/neorv32_litex_core_complex.vhd index 45234a245..626c19ef3 100644 --- a/rtl/system_integration/neorv32_litex_core_complex.vhd +++ b/rtl/system_integration/neorv32_litex_core_complex.vhd @@ -127,7 +127,6 @@ architecture neorv32_litex_core_complex_rtl of neorv32_litex_core_complex is riscv_zicntr : bool_t; riscv_zihpm : bool_t; fast_ops : bool_t; - ipb : natural_t; pmp_nr : natural_t; hpm_nr : natural_t; icache_en : bool_t; @@ -149,7 +148,6 @@ architecture neorv32_litex_core_complex_rtl of neorv32_litex_core_complex is riscv_zicntr => ( false, false, true, true ), -- RISC-V standard CPU counters 'Zicntr' riscv_zihpm => ( false, false, false, true ), -- RISC-V hardware performance monitors 'Zihpm' fast_ops => ( false, false, true, true ), -- use DSPs and barrel-shifters - ipb => ( 2, 2, 4, 4 ), -- instruction prefetch buffer depth, power of two, min 2 pmp_nr => ( 0, 0, 0, 8 ), -- number of PMP regions (0..16) hpm_nr => ( 0, 0, 0, 8 ), -- number of HPM counters (0..29) icache_en => ( false, false, true, true ), -- instruction cache enabled @@ -184,7 +182,6 @@ begin -- Tuning Options -- FAST_MUL_EN => configs_c.fast_ops(CONFIG), -- use DSPs for M extension's multiplier FAST_SHIFT_EN => configs_c.fast_ops(CONFIG), -- use barrel shifter for shift operations - CPU_IPB_ENTRIES => configs_c.ipb(CONFIG), -- entries in instruction prefetch buffer, has to be a power of 2, min 2 -- Physical Memory Protection (PMP) -- PMP_NUM_REGIONS => configs_c.pmp_nr(CONFIG), -- number of regions (0..16) PMP_MIN_GRANULARITY => 4, -- minimal region granularity in bytes, has to be a power of 2, min 4 bytes diff --git a/rtl/test_setups/neorv32_test_setup_approm.vhd b/rtl/test_setups/neorv32_test_setup_approm.vhd index 1458be571..24f65abed 100644 --- a/rtl/test_setups/neorv32_test_setup_approm.vhd +++ b/rtl/test_setups/neorv32_test_setup_approm.vhd @@ -72,8 +72,6 @@ begin CPU_EXTENSION_RISCV_C => true, -- implement compressed extension? CPU_EXTENSION_RISCV_M => true, -- implement mul/div extension? CPU_EXTENSION_RISCV_Zicntr => true, -- implement base counters? - -- Tuning Options -- - CPU_IPB_ENTRIES => 2, -- entries in instruction prefetch buffer, has to be a power of 2, min 1 -- Internal Instruction memory -- MEM_INT_IMEM_EN => true, -- implement processor-internal instruction memory MEM_INT_IMEM_SIZE => MEM_INT_IMEM_SIZE, -- size of processor-internal instruction memory in bytes diff --git a/rtl/test_setups/neorv32_test_setup_bootloader.vhd b/rtl/test_setups/neorv32_test_setup_bootloader.vhd index 358cd1d8e..50d9abffe 100644 --- a/rtl/test_setups/neorv32_test_setup_bootloader.vhd +++ b/rtl/test_setups/neorv32_test_setup_bootloader.vhd @@ -75,8 +75,6 @@ begin CPU_EXTENSION_RISCV_C => true, -- implement compressed extension? CPU_EXTENSION_RISCV_M => true, -- implement mul/div extension? CPU_EXTENSION_RISCV_Zicntr => true, -- implement base counters? - -- Tuning Options -- - CPU_IPB_ENTRIES => 2, -- entries in instruction prefetch buffer, has to be a power of 2, min 1 -- Internal Instruction memory -- MEM_INT_IMEM_EN => true, -- implement processor-internal instruction memory MEM_INT_IMEM_SIZE => MEM_INT_IMEM_SIZE, -- size of processor-internal instruction memory in bytes diff --git a/rtl/test_setups/neorv32_test_setup_on_chip_debugger.vhd b/rtl/test_setups/neorv32_test_setup_on_chip_debugger.vhd index 11c7cf51f..77b800ca1 100644 --- a/rtl/test_setups/neorv32_test_setup_on_chip_debugger.vhd +++ b/rtl/test_setups/neorv32_test_setup_on_chip_debugger.vhd @@ -84,8 +84,6 @@ begin CPU_EXTENSION_RISCV_M => true, -- implement mul/div extension? CPU_EXTENSION_RISCV_Zicntr => true, -- implement base counters? CPU_EXTENSION_RISCV_Zifencei => true, -- implement instruction stream sync.? (required for the on-chip debugger) - -- Tuning Options -- - CPU_IPB_ENTRIES => 2, -- entries in instruction prefetch buffer, has to be a power of 2, min 1 -- Internal Instruction memory -- MEM_INT_IMEM_EN => true, -- implement processor-internal instruction memory MEM_INT_IMEM_SIZE => MEM_INT_IMEM_SIZE, -- size of processor-internal instruction memory in bytes diff --git a/sim/neorv32_tb.vhd b/sim/neorv32_tb.vhd index 26da78365..224e41be9 100644 --- a/sim/neorv32_tb.vhd +++ b/sim/neorv32_tb.vhd @@ -240,7 +240,6 @@ begin -- Extension Options -- FAST_MUL_EN => false, -- use DSPs for M extension's multiplier FAST_SHIFT_EN => false, -- use barrel shifter for shift operations - CPU_IPB_ENTRIES => 1, -- entries is instruction prefetch buffer, has to be a power of 2, min 1 -- Physical Memory Protection (PMP) -- PMP_NUM_REGIONS => 5, -- number of regions (0..16) PMP_MIN_GRANULARITY => 4, -- minimal region granularity in bytes, has to be a power of 2, min 4 bytes diff --git a/sim/simple/neorv32_tb.simple.vhd b/sim/simple/neorv32_tb.simple.vhd index f69539f27..53a402941 100644 --- a/sim/simple/neorv32_tb.simple.vhd +++ b/sim/simple/neorv32_tb.simple.vhd @@ -183,7 +183,6 @@ begin -- Extension Options -- FAST_MUL_EN => true, -- use DSPs for M extension's multiplier FAST_SHIFT_EN => true, -- use barrel shifter for shift operations - CPU_IPB_ENTRIES => 1, -- entries is instruction prefetch buffer, has to be a power of 2, min 1 -- Physical Memory Protection (PMP) -- PMP_NUM_REGIONS => 5, -- number of regions (0..16) PMP_MIN_GRANULARITY => 4, -- minimal region granularity in bytes, has to be a power of 2, min 4 bytes diff --git a/sw/common/common.mk b/sw/common/common.mk index a4ff9cfb3..b051161f3 100644 --- a/sw/common/common.mk +++ b/sw/common/common.mk @@ -130,7 +130,7 @@ IMAGE_GEN = $(NEORV32_EXG_PATH)/image_gen # Compiler & linker flags CC_OPTS = -march=$(MARCH) -mabi=$(MABI) $(EFFORT) -Wall -ffunction-sections -fdata-sections -nostartfiles -mno-fdiv -CC_OPTS += -g -Wl,--gc-sections +CC_OPTS += -mstrict-align -mbranch-cost=10 -g -Wl,--gc-sections CC_OPTS += $(USER_FLAGS) LD_LIBS = -lm -lc -lgcc LD_LIBS += $(USER_LIBS)