From 153a09924e9059fc7aee2e8d0a9461dea2efcdbb Mon Sep 17 00:00:00 2001 From: stnolting <22944758+stnolting@users.noreply.github.com> Date: Thu, 27 Apr 2023 17:02:41 +0200 Subject: [PATCH 1/6] comment edits --- rtl/core/neorv32_dcache.vhd | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/rtl/core/neorv32_dcache.vhd b/rtl/core/neorv32_dcache.vhd index 0986dad8c..4e31be7aa 100644 --- a/rtl/core/neorv32_dcache.vhd +++ b/rtl/core/neorv32_dcache.vhd @@ -83,8 +83,8 @@ architecture neorv32_dcache_rtl of neorv32_dcache is -- cache memory -- component neorv32_dcache_memory generic ( - DCACHE_NUM_BLOCKS : natural := 4; -- number of blocks (min 1), has to be a power of 2 - DCACHE_BLOCK_SIZE : natural := 16 -- block size in bytes (min 4), has to be a power of 2 + DCACHE_NUM_BLOCKS : natural; -- number of blocks (min 1), has to be a power of 2 + DCACHE_BLOCK_SIZE : natural -- block size in bytes (min 4), has to be a power of 2 ); port ( -- global control -- @@ -401,8 +401,8 @@ use neorv32.neorv32_package.all; entity neorv32_dcache_memory is generic ( - DCACHE_NUM_BLOCKS : natural := 4; -- number of blocks (min 1), has to be a power of 2 - DCACHE_BLOCK_SIZE : natural := 16 -- block size in bytes (min 4), has to be a power of 2 + DCACHE_NUM_BLOCKS : natural; -- number of blocks (min 1), has to be a power of 2 + DCACHE_BLOCK_SIZE : natural -- block size in bytes (min 4), has to be a power of 2 ); port ( -- global control -- From df57a102d5dd30f44053cedd78b4129186141eb4 Mon Sep 17 00:00:00 2001 From: stnolting <22944758+stnolting@users.noreply.github.com> Date: Thu, 27 Apr 2023 17:03:19 +0200 Subject: [PATCH 2/6] [rtl] minor CPU bus unit edits --- rtl/core/neorv32_cpu_bus.vhd | 134 ++++++++++++++++--------------- rtl/core/neorv32_cpu_control.vhd | 14 ++-- rtl/core/neorv32_package.vhd | 8 +- 3 files changed, 81 insertions(+), 75 deletions(-) diff --git a/rtl/core/neorv32_cpu_bus.vhd b/rtl/core/neorv32_cpu_bus.vhd index 04d06ec95..d4aa7c555 100644 --- a/rtl/core/neorv32_cpu_bus.vhd +++ b/rtl/core/neorv32_cpu_bus.vhd @@ -96,14 +96,14 @@ architecture neorv32_cpu_bus_rtl of neorv32_cpu_bus is constant pmp_zero_c : std_ulogic_vector(XLEN-1 downto pmp_lsb_c) := (others => '0'); -- misc -- - signal data_sign : std_ulogic; -- signed load signal mar : std_ulogic_vector(XLEN-1 downto 0); -- data memory address register signal misaligned : std_ulogic; -- misaligned address -- bus arbiter -- type bus_arbiter_t is record - pend : std_ulogic; -- pending bus access - err : std_ulogic; -- bus access error + pend_rd : std_ulogic; -- pending bus read access + pend_wr : std_ulogic; -- pending bus write access + acc_err : std_ulogic; -- bus access error pmp_r_err : std_ulogic; -- pmp load fault pmp_w_err : std_ulogic; -- pmp store fault end record; @@ -139,9 +139,12 @@ begin -- Access Address ------------------------------------------------------------------------- -- ------------------------------------------------------------------------------------------- - mem_adr_reg: process(clk_i) + mem_adr_reg: process(rstn_i, clk_i) begin - if rising_edge(clk_i) then + if (rstn_i = '0') then + mar <= (others => '0'); + misaligned <= '0'; + elsif rising_edge(clk_i) then if (ctrl_i.bus_mo_we = '1') then mar <= addr_i; -- memory address register case ctrl_i.ir_funct3(1 downto 0) is -- alignment check @@ -161,9 +164,12 @@ begin -- Write Data: Byte Enable and Alignment -------------------------------------------------- -- ------------------------------------------------------------------------------------------- - mem_do_reg: process(clk_i) + mem_do_reg: process(rstn_i, clk_i) begin - if rising_edge(clk_i) then + if (rstn_i = '0') then + d_bus_wdata_o <= (others => '0'); + d_bus_ben_o <= (others => '0'); + elsif rising_edge(clk_i) then if (ctrl_i.bus_mo_we = '1') then d_bus_ben_o <= (others => '0'); -- default case ctrl_i.ir_funct3(1 downto 0) is @@ -192,72 +198,68 @@ begin -- Read Data: Alignment and Sign-Extension ------------------------------------------------ -- ------------------------------------------------------------------------------------------- - mem_di_reg: process(clk_i) + mem_di_reg: process(rstn_i, clk_i) begin - if rising_edge(clk_i) then - case ctrl_i.ir_funct3(1 downto 0) is - when "00" => -- byte - case mar(1 downto 0) is - when "00" => -- byte 0 - rdata_o(7 downto 0) <= d_bus_rdata_i(07 downto 00); - rdata_o(XLEN-1 downto 8) <= (others => (data_sign and d_bus_rdata_i(07))); -- sign extension - when "01" => -- byte 1 - rdata_o(7 downto 0) <= d_bus_rdata_i(15 downto 08); - rdata_o(XLEN-1 downto 8) <= (others => (data_sign and d_bus_rdata_i(15))); -- sign extension - when "10" => -- byte 2 - rdata_o(7 downto 0) <= d_bus_rdata_i(23 downto 16); - rdata_o(XLEN-1 downto 8) <= (others => (data_sign and d_bus_rdata_i(23))); -- sign extension - when others => -- byte 3 - rdata_o(7 downto 0) <= d_bus_rdata_i(31 downto 24); - rdata_o(XLEN-1 downto 8) <= (others => (data_sign and d_bus_rdata_i(31))); -- sign extension - end case; - when "01" => -- half-word - if (mar(1) = '0') then - rdata_o(15 downto 0) <= d_bus_rdata_i(15 downto 00); -- low half-word - rdata_o(XLEN-1 downto 16) <= (others => (data_sign and d_bus_rdata_i(15))); -- sign extension - else - rdata_o(15 downto 0) <= d_bus_rdata_i(31 downto 16); -- high half-word - rdata_o(XLEN-1 downto 16) <= (others => (data_sign and d_bus_rdata_i(31))); -- sign extension - end if; - when others => -- word - rdata_o(XLEN-1 downto 0) <= d_bus_rdata_i(XLEN-1 downto 0); -- full word - end case; + if (rstn_i = '0') then + rdata_o <= (others => '0'); + elsif rising_edge(clk_i) then + if (arbiter.pend_rd = '1') then -- update only if required (reduce dynamic power) + case ctrl_i.ir_funct3(1 downto 0) is + when "00" => -- byte + case mar(1 downto 0) is + when "00" => -- byte 0 + rdata_o(7 downto 0) <= d_bus_rdata_i(07 downto 00); + rdata_o(XLEN-1 downto 8) <= (others => ((not ctrl_i.ir_funct3(2)) and d_bus_rdata_i(07))); -- sign-ext + when "01" => -- byte 1 + rdata_o(7 downto 0) <= d_bus_rdata_i(15 downto 08); + rdata_o(XLEN-1 downto 8) <= (others => ((not ctrl_i.ir_funct3(2)) and d_bus_rdata_i(15))); -- sign-ext + when "10" => -- byte 2 + rdata_o(7 downto 0) <= d_bus_rdata_i(23 downto 16); + rdata_o(XLEN-1 downto 8) <= (others => ((not ctrl_i.ir_funct3(2)) and d_bus_rdata_i(23))); -- sign-ext + when others => -- byte 3 + rdata_o(7 downto 0) <= d_bus_rdata_i(31 downto 24); + rdata_o(XLEN-1 downto 8) <= (others => ((not ctrl_i.ir_funct3(2)) and d_bus_rdata_i(31))); -- sign-ext + end case; + when "01" => -- half-word + if (mar(1) = '0') then + rdata_o(15 downto 0) <= d_bus_rdata_i(15 downto 00); -- low half-word + rdata_o(XLEN-1 downto 16) <= (others => ((not ctrl_i.ir_funct3(2)) and d_bus_rdata_i(15))); -- sign-ext + else + rdata_o(15 downto 0) <= d_bus_rdata_i(31 downto 16); -- high half-word + rdata_o(XLEN-1 downto 16) <= (others => ((not ctrl_i.ir_funct3(2)) and d_bus_rdata_i(31))); -- sign-ext + end if; + when others => -- word + rdata_o(XLEN-1 downto 0) <= d_bus_rdata_i(XLEN-1 downto 0); -- full word + end case; + end if; end if; end process mem_di_reg; - -- sign extension -- - data_sign <= not ctrl_i.ir_funct3(2); -- NOT unsigned LOAD (LBU, LHU) - -- Access Arbiter ------------------------------------------------------------------------- -- ------------------------------------------------------------------------------------------- data_access_arbiter: process(rstn_i, clk_i) begin if (rstn_i = '0') then - arbiter.pend <= '0'; - arbiter.err <= '0'; + arbiter.pend_rd <= '0'; + arbiter.pend_wr <= '0'; + arbiter.acc_err <= '0'; arbiter.pmp_r_err <= '0'; arbiter.pmp_w_err <= '0'; elsif rising_edge(clk_i) then -- arbiter -- - if (arbiter.pend = '0') then -- idle - if (ctrl_i.bus_req = '1') then -- start bus access - arbiter.pend <= '1'; - end if; - arbiter.err <= '0'; - else -- bus access in progress - -- accumulate bus errors -- - if (d_bus_err_i = '1') or -- bus error - ((ctrl_i.ir_opcode(5) = '1') and (arbiter.pmp_w_err = '1')) or -- PMP store fault - ((ctrl_i.ir_opcode(5) = '0') and (arbiter.pmp_r_err = '1')) then -- PMP load fault - arbiter.err <= '1'; - end if; - -- wait for normal termination or start of trap handling -- - if (d_bus_ack_i = '1') or (ctrl_i.cpu_trap = '1') then - arbiter.pend <= '0'; - end if; + if (arbiter.pend_rd = '0') and (arbiter.pend_wr = '0') then -- idle + arbiter.pend_rd <= ctrl_i.bus_req_rd; + arbiter.pend_wr <= ctrl_i.bus_req_wr; + elsif (d_bus_ack_i = '1') or (ctrl_i.cpu_trap = '1') then -- normal termination or start of trap handling + arbiter.pend_rd <= '0'; + arbiter.pend_wr <= '0'; end if; - -- PMP error -- + -- access error buffer -- + arbiter.acc_err <= d_bus_err_i or -- bus error + (arbiter.pend_rd and arbiter.pmp_r_err) or -- PMP load fault + (arbiter.pend_wr and arbiter.pmp_w_err); -- PMP store fault + -- PMP error buffer -- if (ctrl_i.bus_mo_we = '1') then -- sample PMP errors only once arbiter.pmp_r_err <= ld_pmp_fault; arbiter.pmp_w_err <= st_pmp_fault; @@ -269,14 +271,14 @@ begin d_wait_o <= not d_bus_ack_i; -- output data access error to control unit -- - ma_load_o <= '1' when (arbiter.pend = '1') and (ctrl_i.ir_opcode(5) = '0') and (misaligned = '1') else '0'; - be_load_o <= '1' when (arbiter.pend = '1') and (ctrl_i.ir_opcode(5) = '0') and (arbiter.err = '1') else '0'; - ma_store_o <= '1' when (arbiter.pend = '1') and (ctrl_i.ir_opcode(5) = '1') and (misaligned = '1') else '0'; - be_store_o <= '1' when (arbiter.pend = '1') and (ctrl_i.ir_opcode(5) = '1') and (arbiter.err = '1') else '0'; - - -- data bus control interface (all source signals are driven by registers) -- - d_bus_we_o <= ctrl_i.bus_req and ( ctrl_i.ir_opcode(5)) and (not misaligned) and (not arbiter.pmp_w_err); - d_bus_re_o <= ctrl_i.bus_req and (not ctrl_i.ir_opcode(5)) and (not misaligned) and (not arbiter.pmp_r_err); + ma_load_o <= arbiter.pend_rd and misaligned; + be_load_o <= arbiter.pend_rd and arbiter.acc_err; + ma_store_o <= arbiter.pend_wr and misaligned; + be_store_o <= arbiter.pend_wr and arbiter.acc_err; + + -- data bus control interface (all source signals are driven by registers!) -- + d_bus_re_o <= ctrl_i.bus_req_rd and (not misaligned) and (not arbiter.pmp_r_err); + d_bus_we_o <= ctrl_i.bus_req_wr and (not misaligned) and (not arbiter.pmp_w_err); d_bus_fence_o <= ctrl_i.bus_fence; d_bus_priv_o <= ctrl_i.bus_priv; diff --git a/rtl/core/neorv32_cpu_control.vhd b/rtl/core/neorv32_cpu_control.vhd index a339cce4b..9d0c2f947 100644 --- a/rtl/core/neorv32_cpu_control.vhd +++ b/rtl/core/neorv32_cpu_control.vhd @@ -996,10 +996,10 @@ begin ctrl_nxt.bus_fencei <= '1'; -- FENCE.I execute_engine.state_nxt <= TRAP_EXECUTE; -- use TRAP_EXECUTE to "modify" PC (PC <= PC) else - execute_engine.state_nxt <= DISPATCH; if (execute_engine.ir(instr_funct3_msb_c downto instr_funct3_lsb_c) = funct3_fence_c) then ctrl_nxt.bus_fence <= '1'; -- FENCE end if; + execute_engine.state_nxt <= DISPATCH; end if; @@ -1072,7 +1072,8 @@ begin when MEM_REQ => -- trigger memory request -- ------------------------------------------------------------ if (trap_ctrl.exc_buf(exc_iillegal_c) = '0') then -- not an illegal instruction - ctrl_nxt.bus_req <= '1'; -- trigger memory request + ctrl_nxt.bus_req_rd <= not execute_engine.ir(5); -- read request + ctrl_nxt.bus_req_wr <= execute_engine.ir(5); -- write request end if; execute_engine.state_nxt <= MEM_WAIT; @@ -1147,7 +1148,8 @@ begin ctrl_o.alu_cp_trig <= ctrl.alu_cp_trig; -- bus interface -- - ctrl_o.bus_req <= ctrl.bus_req; + 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; ctrl_o.bus_fence <= ctrl.bus_fence; ctrl_o.bus_fencei <= ctrl.bus_fencei; @@ -2446,9 +2448,9 @@ begin cnt_event(hpmcnt_event_wait_ii_c) <= '1' when (execute_engine.state = DISPATCH) and (execute_engine.state_prev = DISPATCH) else '0'; -- instruction issue wait cycle cnt_event(hpmcnt_event_wait_mc_c) <= '1' when (execute_engine.state = ALU_WAIT) else '0'; -- multi-cycle alu-operation wait cycle - cnt_event(hpmcnt_event_load_c) <= '1' when (ctrl.bus_req = '1') and (execute_engine.ir(instr_opcode_msb_c-1) = '0') else '0'; -- load operation - cnt_event(hpmcnt_event_store_c) <= '1' when (ctrl.bus_req = '1') and (execute_engine.ir(instr_opcode_msb_c-1) = '1') else '0'; -- store operation - cnt_event(hpmcnt_event_wait_ls_c) <= '1' when (execute_engine.state = MEM_WAIT) and (execute_engine.state_prev2 = MEM_WAIT) else '0'; -- load/store memory wait cycle + cnt_event(hpmcnt_event_load_c) <= '1' when (ctrl.bus_req_rd = '1') else '0'; -- load operation + cnt_event(hpmcnt_event_store_c) <= '1' when (ctrl.bus_req_wr = '1') else '0'; -- store operation + cnt_event(hpmcnt_event_wait_ls_c) <= '1' when (execute_engine.state = MEM_WAIT) and (execute_engine.state_prev2 = MEM_WAIT) else '0'; -- load/store memory wait cycle cnt_event(hpmcnt_event_jump_c) <= '1' when (execute_engine.state = BRANCH) and (execute_engine.ir(instr_opcode_lsb_c+2) = '1') else '0'; -- jump (unconditional) cnt_event(hpmcnt_event_branch_c) <= '1' when (execute_engine.state = BRANCH) and (execute_engine.ir(instr_opcode_lsb_c+2) = '0') else '0'; -- branch (conditional, taken or not taken) diff --git a/rtl/core/neorv32_package.vhd b/rtl/core/neorv32_package.vhd index 87afc5fa7..a3d9948f3 100644 --- a/rtl/core/neorv32_package.vhd +++ b/rtl/core/neorv32_package.vhd @@ -60,7 +60,7 @@ package neorv32_package is -- Architecture Constants ----------------------------------------------------------------- -- ------------------------------------------------------------------------------------------- - constant hw_version_c : std_ulogic_vector(31 downto 0) := x"01080403"; -- hardware version + constant hw_version_c : std_ulogic_vector(31 downto 0) := x"01080404"; -- hardware version constant archid_c : natural := 19; -- official RISC-V architecture ID constant XLEN : natural := 32; -- native data path width, do not change! @@ -817,7 +817,8 @@ package neorv32_package is 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 -- - bus_req : std_ulogic; -- trigger memory request + 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 bus_fence : std_ulogic; -- fence operation bus_fencei : std_ulogic; -- fence.i operation @@ -848,7 +849,8 @@ package neorv32_package is alu_unsigned => '0', alu_frm => (others => '0'), alu_cp_trig => (others => '0'), - bus_req => '0', + bus_req_rd => '0', + bus_req_wr => '0', bus_mo_we => '0', bus_fence => '0', bus_fencei => '0', From be1c4f796559acf29fed687100c4ccae6308bc95 Mon Sep 17 00:00:00 2001 From: stnolting <22944758+stnolting@users.noreply.github.com> Date: Thu, 27 Apr 2023 17:23:56 +0200 Subject: [PATCH 3/6] [CHANGELOG] add v1.8.4.4 --- CHANGELOG.md | 1 + 1 file changed, 1 insertion(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index 142395c68..64dadaf05 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -33,6 +33,7 @@ mimpid = 0x01080200 => Version 01.08.02.00 => v1.8.2 | Date (*dd.mm.yyyy*) | Version | Comment | |:-------------------:|:-------:|:--------| +| 27.04.2023 | 1.8.4.4 | minor hardware edits and switching activity optimizations of CPU bus unit; [#605](https://github.com/stnolting/neorv32/pull/605) | | 25.04.2023 | 1.8.4.3 | :bug: fix bug in **DMA** (corrupted write-back when there are bus wait cycles - e.g. when no caches are implemented); [#601](https://github.com/stnolting/neorv32/pull/601) | | 24.04.2023 | 1.8.4.2 | minor rtl edits; shorten critical path of d-cache setup; [#599](https://github.com/stnolting/neorv32/pull/599) | | 22.04.2023 | 1.8.4.1 | :sparkles: add optional **direct memory access controller (DMA)**; [#593](https://github.com/stnolting/neorv32/pull/593) | From 78a4d428129ba5769f42dea3363765f423d3fb49 Mon Sep 17 00:00:00 2001 From: stnolting <22944758+stnolting@users.noreply.github.com> Date: Fri, 28 Apr 2023 09:38:24 +0200 Subject: [PATCH 4/6] [rtl] minor CPU signal renamings RISC-V machine-level interrupts --- rtl/core/neorv32_cpu.vhd | 12 ++++++------ rtl/core/neorv32_package.vhd | 12 ++++++------ rtl/core/neorv32_top.vhd | 6 +++--- 3 files changed, 15 insertions(+), 15 deletions(-) diff --git a/rtl/core/neorv32_cpu.vhd b/rtl/core/neorv32_cpu.vhd index c17760caf..fc4086421 100644 --- a/rtl/core/neorv32_cpu.vhd +++ b/rtl/core/neorv32_cpu.vhd @@ -99,9 +99,9 @@ entity neorv32_cpu is d_bus_fence_o : out std_ulogic; -- executed FENCE operation d_bus_priv_o : out std_ulogic; -- current effective privilege level -- interrupts -- - msw_irq_i : in std_ulogic; -- risc-v: machine software interrupt - mext_irq_i : in std_ulogic; -- risc-v: machine external interrupt - mtime_irq_i : in std_ulogic; -- risc-v: machine timer interrupt + msi_i : in std_ulogic; -- risc-v: machine software interrupt + mei_i : in std_ulogic; -- risc-v: machine external interrupt + mti_i : in std_ulogic; -- risc-v: machine timer interrupt firq_i : in std_ulogic_vector(15 downto 0); -- custom: fast interrupts db_halt_req_i : in std_ulogic -- risc-v: halt request (debug mode) ); @@ -283,9 +283,9 @@ begin -- debug mode (halt) request -- db_halt_req_i => db_halt_req_i, -- interrupts (risc-v compliant) -- - msw_irq_i => msw_irq_i, -- machine software interrupt - mext_irq_i => mext_irq_i, -- machine external interrupt - mtime_irq_i => mtime_irq_i, -- machine timer interrupt + msi_i => msi_i, -- machine software interrupt + mei_i => mei_i, -- machine external interrupt + mti_i => mti_i, -- machine timer interrupt -- fast interrupts (custom) -- firq_i => firq_i, -- fast interrupt trigger -- physical memory protection -- diff --git a/rtl/core/neorv32_package.vhd b/rtl/core/neorv32_package.vhd index a3d9948f3..7642a99f1 100644 --- a/rtl/core/neorv32_package.vhd +++ b/rtl/core/neorv32_package.vhd @@ -1241,9 +1241,9 @@ package neorv32_package is d_bus_fence_o : out std_ulogic; -- executed FENCE operation d_bus_priv_o : out std_ulogic; -- current effective privilege level -- interrupts -- - msw_irq_i : in std_ulogic; -- risc-v: machine software interrupt - mext_irq_i : in std_ulogic; -- risc-v: machine external interrupt - mtime_irq_i : in std_ulogic; -- risc-v: machine timer interrupt + msi_i : in std_ulogic; -- risc-v: machine software interrupt + mei_i : in std_ulogic; -- risc-v: machine external interrupt + mti_i : in std_ulogic; -- risc-v: machine timer interrupt firq_i : in std_ulogic_vector(15 downto 0); -- custom: fast interrupts db_halt_req_i : in std_ulogic -- risc-v: halt request (debug mode) ); @@ -1315,9 +1315,9 @@ package neorv32_package is -- debug mode (halt) request -- db_halt_req_i : in std_ulogic; -- interrupts (risc-v compliant) -- - msw_irq_i : in std_ulogic; -- machine software interrupt - mext_irq_i : in std_ulogic; -- machine external interrupt - mtime_irq_i : in std_ulogic; -- machine timer interrupt + 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); -- physical memory protection -- diff --git a/rtl/core/neorv32_top.vhd b/rtl/core/neorv32_top.vhd index 76a212a07..5ef1a5281 100644 --- a/rtl/core/neorv32_top.vhd +++ b/rtl/core/neorv32_top.vhd @@ -560,9 +560,9 @@ begin d_bus_fence_o => d_fence, -- executed FENCE operation d_bus_priv_o => cpu_d.priv, -- current effective privilege level -- interrupts -- - msw_irq_i => msw_irq_i, -- risc-v: machine software interrupt - mext_irq_i => mext_irq_i, -- risc-v: machine external interrupt - mtime_irq_i => mtime_irq, -- risc-v: machine timer interrupt + msi_i => msw_irq_i, -- risc-v: machine software interrupt + mei_i => mext_irq_i, -- risc-v: machine external interrupt + mti_i => mtime_irq, -- risc-v: machine timer interrupt firq_i => fast_irq, -- custom: fast interrupts db_halt_req_i => dci_halt_req -- risc-v: halt request (debug mode) ); From 3aa633e4ed8ceaddbfe740b7529fa1d1b42e8c2e Mon Sep 17 00:00:00 2001 From: stnolting <22944758+stnolting@users.noreply.github.com> Date: Fri, 28 Apr 2023 09:39:04 +0200 Subject: [PATCH 5/6] [rtl] minor code edits --- rtl/core/neorv32_cpu_bus.vhd | 24 +++++++++++----------- rtl/core/neorv32_cpu_control.vhd | 35 ++++++++++++++++---------------- 2 files changed, 30 insertions(+), 29 deletions(-) diff --git a/rtl/core/neorv32_cpu_bus.vhd b/rtl/core/neorv32_cpu_bus.vhd index d4aa7c555..ee9c4d71a 100644 --- a/rtl/core/neorv32_cpu_bus.vhd +++ b/rtl/core/neorv32_cpu_bus.vhd @@ -241,12 +241,21 @@ begin data_access_arbiter: process(rstn_i, clk_i) begin if (rstn_i = '0') then - arbiter.pend_rd <= '0'; - arbiter.pend_wr <= '0'; - arbiter.acc_err <= '0'; arbiter.pmp_r_err <= '0'; arbiter.pmp_w_err <= '0'; + arbiter.acc_err <= '0'; + arbiter.pend_rd <= '0'; + arbiter.pend_wr <= '0'; elsif rising_edge(clk_i) then + -- PMP error buffer -- + if (ctrl_i.bus_mo_we = '1') then -- sample PMP errors only once + arbiter.pmp_r_err <= ld_pmp_fault; + arbiter.pmp_w_err <= st_pmp_fault; + end if; + -- access error buffer -- + arbiter.acc_err <= d_bus_err_i or -- bus error + (arbiter.pend_rd and arbiter.pmp_r_err) or -- PMP load fault + (arbiter.pend_wr and arbiter.pmp_w_err); -- PMP store fault -- arbiter -- if (arbiter.pend_rd = '0') and (arbiter.pend_wr = '0') then -- idle arbiter.pend_rd <= ctrl_i.bus_req_rd; @@ -255,15 +264,6 @@ begin arbiter.pend_rd <= '0'; arbiter.pend_wr <= '0'; end if; - -- access error buffer -- - arbiter.acc_err <= d_bus_err_i or -- bus error - (arbiter.pend_rd and arbiter.pmp_r_err) or -- PMP load fault - (arbiter.pend_wr and arbiter.pmp_w_err); -- PMP store fault - -- PMP error buffer -- - if (ctrl_i.bus_mo_we = '1') then -- sample PMP errors only once - arbiter.pmp_r_err <= ld_pmp_fault; - arbiter.pmp_w_err <= st_pmp_fault; - end if; end if; end process data_access_arbiter; diff --git a/rtl/core/neorv32_cpu_control.vhd b/rtl/core/neorv32_cpu_control.vhd index 9d0c2f947..2c4ab0e8d 100644 --- a/rtl/core/neorv32_cpu_control.vhd +++ b/rtl/core/neorv32_cpu_control.vhd @@ -113,9 +113,9 @@ entity neorv32_cpu_control is -- debug mode (halt) request -- db_halt_req_i : in std_ulogic; -- interrupts (risc-v compliant) -- - msw_irq_i : in std_ulogic; -- machine software interrupt - mext_irq_i : in std_ulogic; -- machine external interrupt - mtime_irq_i : in std_ulogic; -- machine timer interrupt + 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); -- physical memory protection -- @@ -1071,20 +1071,21 @@ begin when MEM_REQ => -- trigger memory request -- ------------------------------------------------------------ - if (trap_ctrl.exc_buf(exc_iillegal_c) = '0') then -- not an illegal instruction - ctrl_nxt.bus_req_rd <= not execute_engine.ir(5); -- read request - ctrl_nxt.bus_req_wr <= execute_engine.ir(5); -- write request + if (trap_ctrl.exc_buf(exc_iillegal_c) = '1') then -- abort if illegal instruction + execute_engine.state_nxt <= DISPATCH; + else + ctrl_nxt.bus_req_rd <= not execute_engine.ir(5); -- read request + ctrl_nxt.bus_req_wr <= execute_engine.ir(5); -- write request + execute_engine.state_nxt <= MEM_WAIT; end if; - execute_engine.state_nxt <= MEM_WAIT; when MEM_WAIT => -- wait for bus transaction to finish -- ------------------------------------------------------------ ctrl_nxt.rf_mux <= rf_mux_mem_c; -- memory read data -- wait for memory response -- - if ((trap_ctrl.exc_buf(exc_laccess_c) or trap_ctrl.exc_buf(exc_saccess_c) or -- bus access error - trap_ctrl.exc_buf(exc_lalign_c) or trap_ctrl.exc_buf(exc_salign_c) or -- alignment error - trap_ctrl.exc_buf(exc_iillegal_c)) = '1') then -- illegal instruction + if (trap_ctrl.exc_buf(exc_laccess_c) = '1') or (trap_ctrl.exc_buf(exc_saccess_c) = '1') or -- bus access error + (trap_ctrl.exc_buf(exc_lalign_c) = '1') or (trap_ctrl.exc_buf(exc_salign_c) = '1') then -- alignment error execute_engine.state_nxt <= DISPATCH; -- abort! elsif (bus_d_wait_i = '0') then -- wait for bus to finish transaction if (execute_engine.ir(instr_opcode_msb_c-1) = '0') then -- load @@ -1479,9 +1480,9 @@ begin -- ---------------------------------------------------------------------- -- RISC-V machine interrupts -- - trap_ctrl.irq_pnd(irq_msi_irq_c) <= msw_irq_i; - trap_ctrl.irq_pnd(irq_mei_irq_c) <= mext_irq_i; - trap_ctrl.irq_pnd(irq_mti_irq_c) <= mtime_irq_i; + trap_ctrl.irq_pnd(irq_msi_irq_c) <= msi_i; + trap_ctrl.irq_pnd(irq_mei_irq_c) <= mei_i; + trap_ctrl.irq_pnd(irq_mti_irq_c) <= mti_i; -- NEORV32-specific fast interrupts -- for i in 0 to 15 loop @@ -1530,11 +1531,11 @@ begin trap_ctrl.wakeup <= '0'; trap_ctrl.env_start <= '0'; elsif rising_edge(clk_i) then - trap_ctrl.wakeup <= or_reduce_f(trap_ctrl.irq_buf); -- wakeup from sleep due to any pending IRQ (including debug IRQs!) + trap_ctrl.wakeup <= or_reduce_f(trap_ctrl.irq_buf); -- wakeup from sleep on any pending IRQ (including debug IRQs) if (trap_ctrl.env_start = '0') then -- no started trap handler 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_start <= '1'; -- now execute engine can start trap handler + trap_ctrl.env_start <= '1'; -- now execute engine can start trap handling end if; else -- trap environment ready to start if (trap_ctrl.env_start_ack = '1') then -- start of trap handler acknowledged by execute engine @@ -1547,7 +1548,7 @@ begin -- any exception? -- trap_ctrl.exc_fire <= '1' when (or_reduce_f(trap_ctrl.exc_buf) = '1') else '0'; -- sync. exceptions CANNOT be masked - -- valid interrupt request? -- + -- any interrupt? -- trap_ctrl.irq_fire <= '1' when ( (or_reduce_f(trap_ctrl.irq_buf(irq_firq_15_c downto irq_msi_irq_c)) = '1') and -- pending machine IRQ @@ -1600,7 +1601,7 @@ begin elsif (trap_ctrl.irq_buf(irq_firq_15_c) = '1') then trap_ctrl.cause <= trap_firq15_c; -- fast interrupt channel 15 -- standard RISC-V interrupts -- elsif (trap_ctrl.irq_buf(irq_mei_irq_c) = '1') then trap_ctrl.cause <= trap_mei_c; -- machine external interrupt (MEI) - elsif (trap_ctrl.irq_buf(irq_msi_irq_c) = '1') then trap_ctrl.cause <= trap_msi_c; -- machine SW interrupt (MSI) + elsif (trap_ctrl.irq_buf(irq_msi_irq_c) = '1') then trap_ctrl.cause <= trap_msi_c; -- machine software interrupt (MSI) elsif (trap_ctrl.irq_buf(irq_mti_irq_c) = '1') then trap_ctrl.cause <= trap_mti_c; -- machine timer interrupt (MTI) else trap_ctrl.cause <= trap_mti_c; end if; -- don't care end if; From 246b6cb39d4a96f89958ec199c121f8284bf8430 Mon Sep 17 00:00:00 2001 From: stnolting <22944758+stnolting@users.noreply.github.com> Date: Fri, 28 Apr 2023 09:59:05 +0200 Subject: [PATCH 6/6] update script to VUnit v5 --- sim/run.py | 1 + 1 file changed, 1 insertion(+) diff --git a/sim/run.py b/sim/run.py index c4d74417b..eef61d87a 100755 --- a/sim/run.py +++ b/sim/run.py @@ -14,6 +14,7 @@ args = cli.parse_args() PRJ = VUnit.from_args(args=args) +PRJ.add_vhdl_builtins() PRJ.add_com() PRJ.add_verification_components() PRJ.add_osvvm()