Skip to content
New issue

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

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

Already on GitHub? Sign in to your account

🐛 Make sure IMEM/DMEM sizes are a power of two #658

Merged
merged 5 commits into from
Jul 27, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
7 changes: 4 additions & 3 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -6,9 +6,9 @@ Releases are linked and highlighted. The latest release is
A list of all releases can be found [here](https://github.com/stnolting/neorv32/releases).

Starting with version `1.5.7` this project uses [semantic versioning](https://semver.org).
The _version identifier_ uses an additional **custom** element (`MAJOR.MINOR.PATCH.custom`)
to track _individual_ changes. The identifier number is incremented with every core RTL
modification and also by major framework modifications.
The **version identifier** uses an additional custom element (`MAJOR.MINOR.PATCH.custom`)
to track individual changes. The identifier is incremented by every core RTL modification
and also by major software/project changes.

The version identifier is globally defined by the `hw_version_c` constant in the main VHDL
[package file](https://github.com/stnolting/neorv32/blob/main/rtl/core/neorv32_package.vhd).
Expand All @@ -32,6 +32,7 @@ mimpid = 0x01040312 -> Version 01.04.03.12 -> v1.4.3.12

| Date (*dd.mm.yyyy*) | Version | Comment |
|:-------------------:|:-------:|:--------|
| 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) |
| 26.07.2023 | [**:rocket:1.8.7**](https://github.com/stnolting/neorv32/releases/tag/v1.8.7) | **New release** |
| 24.07.2023 | 1.8.6.10 | :bug: fixing some LR/SC design flaws; [#654](https://github.com/stnolting/neorv32/pull/654) |
Expand Down
4 changes: 2 additions & 2 deletions docs/datasheet/soc.adoc
Original file line number Diff line number Diff line change
Expand Up @@ -232,10 +232,10 @@ The generic type "`suv(x:y)`" is an abbreviation for "`std_ulogic_vector(x downt
| `AMO_RVS_GRANULARITY` | natural | 4 | Size in bytes, has to be a power of 2, min 4.
4+^| **Internal <<_instruction_memory_imem>>**
| `MEM_INT_IMEM_EN` | boolean | false | Implement the processor-internal instruction memory.
| `MEM_INT_IMEM_SIZE` | natural | 16*1024 | Size in bytes of the processor internal instruction memory.
| `MEM_INT_IMEM_SIZE` | natural | 16*1024 | Size in bytes of the processor internal instruction memory (use a power of 2).
4+^| **Internal <<_data_memory_dmem>>**
| `MEM_INT_DMEM_EN` | boolean | false | Implement the processor-internal data memory.
| `MEM_INT_DMEM_SIZE` | natural | 8*1024 | Size in bytes of the processor-internal data memory.
| `MEM_INT_DMEM_SIZE` | natural | 8*1024 | Size in bytes of the processor-internal data memory (use a power of 2).
4+^| **<<_processor_internal_instruction_cache_icache>>**
| `ICACHE_EN` | boolean | false | Implement the instruction cache.
| `ICACHE_NUM_BLOCKS` | natural | 4 | Number of blocks ("pages" or "lines") Has to be a power of two.
Expand Down
8 changes: 7 additions & 1 deletion docs/datasheet/soc_dmem.adoc
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@
| Software driver file(s): | none | _implicitly used_
| Top entity port: | none |
| Configuration generics: | `MEM_INT_DMEM_EN` | implement processor-internal DMEM when `true`
| | `MEM_INT_DMEM_SIZE` | DMEM size in bytes
| | `MEM_INT_DMEM_SIZE` | DMEM size in bytes (use a power of 2)
| CPU interrupts: | none |
|=======================

Expand All @@ -20,6 +20,12 @@ the memory is mapped into the data memory space and located right at the beginni
space (default `dspace_base_c` = 0x80000000), see <<_address_space>>. The DMEM is always implemented
as true RAM.

.Memory Size
[IMPORTANT]
If the configured memory size (via the `MEM_INT_IMEM_SIZE` generic) is **not** a power of two the actual memory
size will be auto-adjusted to the next power of two (e.g. configuring a memory size of 60kB will result in a
physical memory size of 64kB).

.VHDL Source File
[NOTE]
The actual DMEM is split into two design files: a plain entity definition (`neorv32_dmem.entity.vhd`) and the actual
Expand Down
8 changes: 7 additions & 1 deletion docs/datasheet/soc_imem.adoc
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@
| Software driver file(s): | none | _implicitly used_
| Top entity port: | none |
| Configuration generics: | `MEM_INT_IMEM_EN` | implement processor-internal IMEM when `true`
| | `MEM_INT_IMEM_SIZE` | IMEM size in bytes
| | `MEM_INT_IMEM_SIZE` | IMEM size in bytes (use a power of 2)
| | `INT_BOOTLOADER_EN` | use internal bootloader when `true` (implements IMEM as _uninitialized_ RAM, otherwise the IMEM is implemented an _pre-intialized_ ROM)
| CPU interrupts: | none |
|=======================
Expand All @@ -31,6 +31,12 @@ image. The compiler toolchain provides an option to generate and override the de
`rtl/core/neorv32_application_image.vhd`, which is automatically inserted into the IMEM. If the IMEM is implemented
as RAM (default), the memory will **not be initialized at all**.

.Memory Size
[IMPORTANT]
If the configured memory size (via the `MEM_INT_IMEM_SIZE` generic) is **not** a power of two the actual memory
size will be auto-adjusted to the next power of two (e.g. configuring a memory size of 60kB will result in a
physical memory size of 64kB).

.VHDL Source File
[NOTE]
The actual IMEM is split into two design files: a plain entity definition (`neorv32_imem.entity.vhd`) and the actual
Expand Down
3 changes: 3 additions & 0 deletions rtl/core/mem/neorv32_dmem.default.vhd
Original file line number Diff line number Diff line change
Expand Up @@ -68,6 +68,9 @@ begin
assert false report
"NEORV32 PROCESSOR CONFIG NOTE: Using DEFAULT platform-agnostic DMEM." severity note;

assert not (is_power_of_two_f(DMEM_SIZE) = false) report
"NEORV32 PROCESSOR CONFIG ERROR: Internal DMEM size has to be a power of two!" severity error;

assert false report
"NEORV32 PROCESSOR CONFIG NOTE: Implementing processor-internal DMEM (RAM, " & natural'image(DMEM_SIZE) &
" bytes)." severity note;
Expand Down
3 changes: 3 additions & 0 deletions rtl/core/mem/neorv32_dmem.legacy.vhd
Original file line number Diff line number Diff line change
Expand Up @@ -69,6 +69,9 @@ begin
assert false report
"NEORV32 PROCESSOR CONFIG NOTE: Using legacy HDL style DMEM." severity note;

assert not (is_power_of_two_f(DMEM_SIZE) = false) report
"NEORV32 PROCESSOR CONFIG ERROR: Internal DMEM size has to be a power of two!" severity error;

assert false report
"NEORV32 PROCESSOR CONFIG NOTE: Implementing processor-internal DMEM (RAM, " & natural'image(DMEM_SIZE) &
" bytes)." severity note;
Expand Down
3 changes: 3 additions & 0 deletions rtl/core/mem/neorv32_imem.default.vhd
Original file line number Diff line number Diff line change
Expand Up @@ -85,6 +85,9 @@ begin
assert false report
"NEORV32 PROCESSOR CONFIG NOTE: Using DEFAULT platform-agnostic IMEM." severity note;

assert not (is_power_of_two_f(IMEM_SIZE) = false) report
"NEORV32 PROCESSOR CONFIG ERROR: Internal IMEM size has to be a power of two!" severity error;

assert not (IMEM_AS_IROM = true) report
"NEORV32 PROCESSOR CONFIG NOTE: Implementing processor-internal IMEM as ROM (" & natural'image(IMEM_SIZE) &
" bytes), pre-initialized with application (" & natural'image(imem_app_size_c) & " bytes)." severity note;
Expand Down
3 changes: 3 additions & 0 deletions rtl/core/mem/neorv32_imem.legacy.vhd
Original file line number Diff line number Diff line change
Expand Up @@ -86,6 +86,9 @@ begin
assert false report
"NEORV32 PROCESSOR CONFIG NOTE: Using legacy HDL style IMEM." severity note;

assert not (is_power_of_two_f(IMEM_SIZE) = false) report
"NEORV32 PROCESSOR CONFIG ERROR: Internal IMEM size has to be a power of two!" severity error;

assert not (IMEM_AS_IROM = true) report
"NEORV32 PROCESSOR CONFIG NOTE: Implementing processor-internal IMEM as ROM (" & natural'image(IMEM_SIZE) &
" bytes), pre-initialized with application (" & natural'image(imem_app_size_c) & " bytes)." severity note;
Expand Down
2 changes: 1 addition & 1 deletion rtl/core/neorv32_dmem.entity.vhd
Original file line number Diff line number Diff line change
Expand Up @@ -41,7 +41,7 @@ use neorv32.neorv32_package.all;

entity neorv32_dmem is
generic (
DMEM_SIZE : natural -- processor-internal instruction memory size in bytes
DMEM_SIZE : natural -- processor-internal instruction memory size in bytes, has to be a power of 2
);
port (
clk_i : in std_ulogic; -- global clock line
Expand Down
2 changes: 1 addition & 1 deletion rtl/core/neorv32_imem.entity.vhd
Original file line number Diff line number Diff line change
Expand Up @@ -41,7 +41,7 @@ use neorv32.neorv32_package.all;

entity neorv32_imem is
generic (
IMEM_SIZE : natural; -- processor-internal instruction memory size in bytes
IMEM_SIZE : natural; -- processor-internal instruction memory size in bytes, has to be a power of 2
IMEM_AS_IROM : boolean -- implement IMEM as pre-initialized read-only memory?
);
port (
Expand Down
6 changes: 3 additions & 3 deletions rtl/core/neorv32_package.vhd
Original file line number Diff line number Diff line change
Expand Up @@ -56,7 +56,7 @@ package neorv32_package is

-- Architecture Constants -----------------------------------------------------------------
-- -------------------------------------------------------------------------------------------
constant hw_version_c : std_ulogic_vector(31 downto 0) := x"01080701"; -- hardware version
constant hw_version_c : std_ulogic_vector(31 downto 0) := x"01080702"; -- hardware version
constant archid_c : natural := 19; -- official RISC-V architecture ID
constant XLEN : natural := 32; -- native data path width, do not change!

Expand Down Expand Up @@ -919,10 +919,10 @@ package neorv32_package is
AMO_RVS_GRANULARITY : natural := 4; -- size in bytes, has to be a power of 2, min 4
-- Internal Instruction memory (IMEM) --
MEM_INT_IMEM_EN : boolean := false; -- implement processor-internal instruction memory
MEM_INT_IMEM_SIZE : natural := 16*1024; -- size of processor-internal instruction memory in bytes
MEM_INT_IMEM_SIZE : natural := 16*1024; -- size of processor-internal instruction memory in bytes (use a power of 2)
-- Internal Data memory (DMEM) --
MEM_INT_DMEM_EN : boolean := false; -- implement processor-internal data memory
MEM_INT_DMEM_SIZE : natural := 8*1024; -- size of processor-internal data memory in bytes
MEM_INT_DMEM_SIZE : natural := 8*1024; -- size of processor-internal data memory in bytes (use a power of 2)
-- Internal Instruction Cache (iCACHE) --
ICACHE_EN : boolean := false; -- implement instruction cache
ICACHE_NUM_BLOCKS : natural := 4; -- i-cache: number of blocks (min 1), has to be a power of 2
Expand Down
45 changes: 28 additions & 17 deletions rtl/core/neorv32_top.vhd
Original file line number Diff line number Diff line change
Expand Up @@ -88,11 +88,11 @@ entity neorv32_top is

-- Internal Instruction memory (IMEM) --
MEM_INT_IMEM_EN : boolean := false; -- implement processor-internal instruction memory
MEM_INT_IMEM_SIZE : natural := 16*1024; -- size of processor-internal instruction memory in bytes
MEM_INT_IMEM_SIZE : natural := 16*1024; -- size of processor-internal instruction memory in bytes (use a power of 2)

-- Internal Data memory (DMEM) --
MEM_INT_DMEM_EN : boolean := false; -- implement processor-internal data memory
MEM_INT_DMEM_SIZE : natural := 8*1024; -- size of processor-internal data memory in bytes
MEM_INT_DMEM_SIZE : natural := 8*1024; -- size of processor-internal data memory in bytes (use a power of 2)

-- Internal Instruction Cache (iCACHE) --
ICACHE_EN : boolean := false; -- implement instruction cache
Expand Down Expand Up @@ -261,6 +261,15 @@ architecture neorv32_top_rtl of neorv32_top is
constant io_xirq_en_c : boolean := boolean(XIRQ_NUM_CH > 0);
constant io_pwm_en_c : boolean := boolean(IO_PWM_NUM_CH > 0);

-- make sure physical memory sizes are a power of two --
constant imem_size_valid_c : boolean := is_power_of_two_f(MEM_INT_IMEM_SIZE);
constant imem_size_pow2_c : natural := 2**index_size_f(MEM_INT_IMEM_SIZE);
constant imem_size_c : natural := cond_sel_natural_f(imem_size_valid_c, MEM_INT_IMEM_SIZE, imem_size_pow2_c);
--
constant dmem_size_valid_c : boolean := is_power_of_two_f(MEM_INT_DMEM_SIZE);
constant dmem_size_pow2_c : natural := 2**index_size_f(MEM_INT_DMEM_SIZE);
constant dmem_size_c : natural := cond_sel_natural_f(dmem_size_valid_c, MEM_INT_DMEM_SIZE, dmem_size_pow2_c);

-- reset generator --
signal rstn_ext_sreg, rstn_int_sreg : std_ulogic_vector(3 downto 0);
signal rstn_ext, rstn_int, rstn_wdt : std_ulogic;
Expand Down Expand Up @@ -381,11 +390,13 @@ begin
assert not ((INT_BOOTLOADER_EN = false) and (MEM_INT_IMEM_EN = false)) report
"NEORV32 PROCESSOR CONFIG NOTE: Boot configuration = direct boot from memory (processor-external memory)." severity note;

-- memory layout --
assert not (mem_ispace_base_c /= x"00000000") report
"NEORV32 PROCESSOR CONFIG WARNING! Non-default base address for INSTRUCTION ADDRESS SPACE. Make sure this is sync with the software framework." severity warning;
assert not (mem_dspace_base_c /= x"80000000") report
"NEORV32 PROCESSOR CONFIG WARNING! Non-default base address for DATA ADDRESS SPACE. Make sure this is sync with the software framework." severity warning;
-- internal memory sizes --
assert not ((imem_size_valid_c = false) and (MEM_INT_IMEM_EN = true)) report
"NEORV32 PROCESSOR CONFIG WARNING: Configured internal IMEM size (" & natural'image(MEM_INT_IMEM_SIZE) & " bytes) is not a power of two. " &
"Auto-increasing memory size to the next power of two (" & natural'image(imem_size_c) & " bytes)" severity warning;
assert not ((dmem_size_valid_c = false) and (MEM_INT_DMEM_EN = true)) report
"NEORV32 PROCESSOR CONFIG WARNING: Configured internal DMEM size (" & natural'image(MEM_INT_DMEM_SIZE) & " bytes) is not a power of two. " &
"Auto-increasing memory size to the next power of two (" & natural'image(dmem_size_c) & " bytes)" severity warning;

-- on-chip debugger --
assert not (ON_CHIP_DEBUGGER_EN = true) report
Expand Down Expand Up @@ -719,11 +730,11 @@ begin
-- IMEM port --
IMEM_ENABLE => MEM_INT_IMEM_EN,
IMEM_BASE => mem_ispace_base_c,
IMEM_SIZE => MEM_INT_IMEM_SIZE,
IMEM_SIZE => imem_size_c,
-- DMEM port --
DMEM_ENABLE => MEM_INT_DMEM_EN,
DMEM_BASE => mem_dspace_base_c,
DMEM_SIZE => MEM_INT_DMEM_SIZE,
DMEM_SIZE => dmem_size_c,
-- XIP port --
XIP_ENABLE => IO_XIP_EN,
XIP_BASE => mem_xip_base_c,
Expand Down Expand Up @@ -773,10 +784,10 @@ begin
-- Processor-Internal Instruction Memory (IMEM) -------------------------------------------
-- -------------------------------------------------------------------------------------------
neorv32_int_imem_inst_true:
if (MEM_INT_IMEM_EN = true) and (MEM_INT_IMEM_SIZE > 0) generate
if (MEM_INT_IMEM_EN = true) and (imem_size_c > 0) generate
neorv32_int_imem_inst: entity neorv32.neorv32_imem
generic map (
IMEM_SIZE => MEM_INT_IMEM_SIZE,
IMEM_SIZE => imem_size_c,
IMEM_AS_IROM => imem_as_rom_c
)
port map (
Expand All @@ -787,18 +798,18 @@ begin
end generate;

neorv32_int_imem_inst_false:
if (MEM_INT_IMEM_EN = false) or (MEM_INT_IMEM_SIZE = 0) generate
if (MEM_INT_IMEM_EN = false) or (imem_size_c = 0) generate
imem_rsp <= rsp_terminate_c;
end generate;


-- Processor-Internal Data Memory (DMEM) --------------------------------------------------
-- -------------------------------------------------------------------------------------------
neorv32_int_dmem_inst_true:
if (MEM_INT_DMEM_EN = true) and (MEM_INT_DMEM_SIZE > 0) generate
if (MEM_INT_DMEM_EN = true) and (dmem_size_c > 0) generate
neorv32_int_dmem_inst: entity neorv32.neorv32_dmem
generic map (
DMEM_SIZE => MEM_INT_DMEM_SIZE
DMEM_SIZE => dmem_size_c
)
port map (
clk_i => clk_i,
Expand All @@ -808,7 +819,7 @@ begin
end generate;

neorv32_int_dmem_inst_false:
if (MEM_INT_DMEM_EN = false) or (MEM_INT_DMEM_SIZE = 0) generate
if (MEM_INT_DMEM_EN = false) or (dmem_size_c = 0) generate
dmem_rsp <= rsp_terminate_c;
end generate;

Expand Down Expand Up @@ -1473,10 +1484,10 @@ begin
PMP_NUM_REGIONS => PMP_NUM_REGIONS,
-- internal Instruction memory --
MEM_INT_IMEM_EN => MEM_INT_IMEM_EN,
MEM_INT_IMEM_SIZE => MEM_INT_IMEM_SIZE,
MEM_INT_IMEM_SIZE => imem_size_c,
-- Internal Data memory --
MEM_INT_DMEM_EN => MEM_INT_DMEM_EN,
MEM_INT_DMEM_SIZE => MEM_INT_DMEM_SIZE,
MEM_INT_DMEM_SIZE => dmem_size_c,
-- Instruction cache --
ICACHE_EN => ICACHE_EN,
ICACHE_NUM_BLOCKS => ICACHE_NUM_BLOCKS,
Expand Down