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

⚠️ Relocate VUnit testbench to another sub-repository (neorv32-vunit) #1083

Merged
merged 7 commits into from
Nov 1, 2024
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
39 changes: 2 additions & 37 deletions .github/workflows/Processor.yml
Original file line number Diff line number Diff line change
Expand Up @@ -32,10 +32,9 @@ jobs:
make -C sw/example clean_all exe
make -C sw/bootloader clean_all info bootloader


Simple:
Default_TB:
runs-on: ubuntu-latest
name: 'Simple testbench'
name: 'Default testbench'
strategy:
fail-fast: false
matrix:
Expand All @@ -61,37 +60,3 @@ jobs:
info
all
sim-check


VUnit:
runs-on: ubuntu-latest

steps:

- name: '🧰 Repository Checkout'
uses: actions/checkout@v4

- name: '⚙️ Build and install Processor Check software'
uses: docker://ghcr.io/stnolting/neorv32/sim
with:
args: >-
make -C sw/example/processor_check
clean_all
USER_FLAGS+=-DUART0_SIM_MODE
USER_FLAGS+=-DSUPPRESS_OPTIONAL_UART_PRINT
USER_FLAGS+=-flto
MARCH=rv32imac_zicsr_zifencei
info
all

- name: '📤 Archive Processor Check application image'
uses: actions/upload-artifact@v4
with:
name: application
path: rtl/core/neorv32_application_image.vhd

- name: '🚧 Run Processor Hardware Tests with VUnit'
uses: VUnit/vunit_action@master
with:
image: ghcr.io/stnolting/neorv32/sim
cmd: ./sim/run.py --ci-mode -v
1 change: 1 addition & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -73,6 +73,7 @@ not working as expected. See how to [contribute](https://github.com/stnolting/ne
| GitHub pages (docs) | [neorv32](https://github.com/stnolting/neorv32) | [![GitHub Pages](https://img.shields.io/website.svg?label=stnolting.github.io%2Fneorv32&longCache=true&style=flat-square&url=http%3A%2F%2Fstnolting.github.io%2Fneorv32%2Findex.html&logo=GitHub)](https://stnolting.github.io/neorv32) |
| Build documentation | [neorv32](https://github.com/stnolting/neorv32) | [![Documentation](https://img.shields.io/github/actions/workflow/status/stnolting/neorv32/Documentation.yml?branch=main&longCache=true&style=flat-square&label=Documentation&logo=Github%20Actions&logoColor=fff)](https://github.com/stnolting/neorv32/actions?query=workflow%3ADocumentation) |
| Processor verification | [neorv32](https://github.com/stnolting/neorv32) | [![Processor](https://img.shields.io/github/actions/workflow/status/stnolting/neorv32/Processor.yml?branch=main&longCache=true&style=flat-square&label=Processor%20Check&logo=Github%20Actions&logoColor=fff)](https://github.com/stnolting/neorv32/actions?query=workflow%3AProcessor) |
| VUnit testbench | [neorv32-vunit](https://github.com/stnolting/neorv32-vunit) | [![neorv32-vunit](https://img.shields.io/github/actions/workflow/status/stnolting/neorv32-vunit/vunit.yml?branch=main&longCache=true&style=flat-square&label=neorv32-vunit&logo=Github%20Actions&logoColor=fff)](https://github.com/stnolting/neorv32-vunit/actions/workflows/vunit.yml) |
| RISCOF core verification | [neorv32-riscof](https://github.com/stnolting/neorv32-riscof) | [![neorv32-riscof](https://img.shields.io/github/actions/workflow/status/stnolting/neorv32-riscof/main.yml?branch=main&longCache=true&style=flat-square&label=neorv32-riscof&logo=Github%20Actions&logoColor=fff)](https://github.com/stnolting/neorv32-riscof/actions/workflows/main.yml) |
| FPGA implementations | [neorv32-setups](https://github.com/stnolting/neorv32-setups) | [![Implementation](https://img.shields.io/github/actions/workflow/status/stnolting/neorv32-setups/Implementation.yml?branch=main&longCache=true&style=flat-square&label=Implementation&logo=Github%20Actions&logoColor=fff)](https://github.com/stnolting/neorv32-setups/actions?query=workflow%3AImplementation) |
| All-Verilog version | [neorv32-verilog](https://github.com/stnolting/neorv32-verilog) | [![neorv32-verilog](https://img.shields.io/github/actions/workflow/status/stnolting/neorv32-verilog/main.yml?branch=main&longCache=true&style=flat-square&label=neorv32-verilog&logo=Github%20Actions&logoColor=fff)](https://github.com/stnolting/neorv32-verilog/actions/workflows/main.yml) |
Expand Down
2 changes: 1 addition & 1 deletion docs/datasheet/overview.adoc
Original file line number Diff line number Diff line change
Expand Up @@ -284,7 +284,7 @@ puts $file_list

.File-List Usage Examples
[TIP]
The provided file-list files are used by the GHDL-based simple simulation setup (`sim/tb_simple/ghdl.setup.sh`) as
The provided file-list files are used by the GHDL-based simple simulation setup (`sim/ghdl.setup.sh`) as
well as by the Vivado IP packager script (`rtl/system_integration/neorv32_vivado_ip.tcl`).


Expand Down
107 changes: 14 additions & 93 deletions docs/userguide/simulating_the_processor.adoc
Original file line number Diff line number Diff line change
Expand Up @@ -2,9 +2,9 @@
:sectnums:
== Simulating the Processor

The NEORV32 project includes a core CPU, built-in peripherals in the Processor Subsystem, and additional peripherals in
the templates and examples.
Therefore, there is a wide range of possible testing and verification strategies.
The NEORV32 project includes a core CPU, built-in peripherals in the Processor Subsystem, and additional
peripherals in the templates and examples. Therefore, there is a wide range of possible testing and
verification strategies.

On the one hand, a simple smoke testbench allows ensuring that functionality is correct from a software point of view.
That is used for running the RISC-V architecture tests, in order to guarantee compliance with the ISA specification(s).
Expand All @@ -13,27 +13,22 @@ On the other hand, http://vunit.github.io/[VUnit] and http://vunit.github.io/ver
are used for verifying the functionality of the various peripherals from a hardware point of view.

.AMD Vivado / ISIM
[IMPORTANT]
[TIP]
When using AMD Vivado (ISIM for simulation) make sure to **turn of** "incremental compilation" (_Project Setting_
-> _Simulation_ -> _Advanced_ -> _Enable incremental compilation). This will slow down simulation relaunch but will
ensure that all application images (`*_image.vhd`) are reanalyzed when recompiling the NEORV32 application or bootloader

[TIP]
The processor can check if it is being _simulated_ by checking the SYSINFO _SYSINFO_SOC_IS_SIM_ flag
(see https://stnolting.github.io/neorv32/#_system_configuration_information_memory_sysinfo).
Note that this flag is not guaranteed to be set correctly (depending on the HDL toolchain's pragma support).

:sectnums:
=== Testbench

A plain-VHDL (no third-party libraries) testbench (`sim/simple/neorv32_tb.simple.vhd`) can be used for simulating and
testing the processor.
This testbench features a 100MHz clock and enables all optional peripheral and CPU extensions except for the `E`.
.VUnit Testbench
[TIP]
A more sophisticated testbench using **VUnit** is available in a separate repository:
https://github.com/stnolting/neorv32-vunit

[IMPORTANT]
In the simple testbench several optional extensions are disabled, such as C or E.
If software is compiled using instructions corresponding to disabled extensions, the whole processor will hang in an eternal exception loop and, therefore, the simulation will timeout.
The `MARCH` must be a subset of the extensions enabled in the testbench.
A plain-VHDL (no third-party libraries) testbench (`sim/neorv32_tb.vhd`) can be used for simulating and
testing the processor. This testbench features a 100MHz clock and enables all optional peripheral and CPU
extensions.

.True Random Number Generator
[NOTE]
Expand All @@ -43,40 +38,6 @@ by pseudo-random LFSRs). See the neoTRNG documentation for more information.
The simulation setup is configured via the "User Configuration" section located right at the beginning of
the testbench's architecture. Each configuration constant provides comments to explain the functionality.

Besides the actual NEORV32 Processor, the testbench also simulates "external" components that are connected
to the processor's external bus/memory interface. These components are:

* an external instruction memory (that also allows booting from it)
* an external data memory
* an external memory to simulate "external IO devices"
* a memory-mapped registers to trigger the processor's interrupt signals

The following table shows the base addresses of these four components and their default configuration and
properties:

[NOTE]
====
Attributes:

* `r` = read
* `w` = write
* `e` = execute
* `8` = byte-accessible
* `16` = half-word-accessible
* `32` = word-accessible
====

.Testbench: processor-external memories
[cols="^4,>3,^5,<11"]
[options="header",grid="rows"]
|=======================
| Base address | Size | Attributes | Description
| `0x00000000` | `imem_size_c` | `r/w/e 8/16/32` | external IMEM (initialized with application image)
| `0x80000000` | `dmem_size_c` | `r/w/e 8/16/32` | external DMEM
| `0xf0000000` | 64 bytes | `r/w/e 8/16/32` | external "IO" memory
| `0xff000000` | 4 bytes | `-/w/- -/-/32` | memory-mapped register to trigger "machine external", "machine software" and "SoC Fast Interrupt" interrupts
|=======================

[IMPORTANT]
The simulated NEORV32 does not use the bootloader and _directly boots_ the current application image (from
the `rtl/core/neorv32_application_image.vhd` image file).
Expand All @@ -100,7 +61,7 @@ for UART0/UART1 (see section https://stnolting.github.io/neorv32/#_primary_unive
ASCII data sent to UART0|UART1 will be immediately printed to the simulator console and logged to files in the simulator
execution directory:

* `neorv32.uart?.sim_mode.text.out`: ASCII data.
* `neorv32.uart*.sim_mode.text.out`: ASCII data.

You can "automatically" enable the simulation mode of UART0/UART1 when compiling an application.
In this case, the "real" UART0/UART1 transmitter unit is permanently disabled.
Expand All @@ -123,13 +84,13 @@ completed with a line feed (newline, ASCII `\n` = 10).
:sectnums:
=== Simulation using a shell script (with GHDL)

To simulate the processor using _GHDL_ navigate to the `sim/simple/` folder and run the provided shell script.
To simulate the processor using _GHDL_ navigate to the `sim` folder and run the provided shell script.
Any arguments that are provided while executing this script are passed to GHDL.
For example the simulation time can be set to 20ms using `--stop-time=20ms` as argument.

[source, bash]
----
neorv32/sim/simple$ sh ghdl.sh --stop-time=20ms
neorv32/sim$ sh ghdl.sh --stop-time=20ms
----


Expand All @@ -156,10 +117,6 @@ To do a quick test of the NEORV32 make sure to have https://github.com/ghdl/ghdl
https://github.com/stnolting/riscv-gcc-prebuilt[RISC-V gcc toolchain] installed.
Navigate to the project's `sw/example/hello_world` folder and run `make USER_FLAGS+=-DUART0_SIM_MODE clean_all sim`:

[TIP]
The simulator will output some _sanity check_ notes (and warnings or even errors if something is ill-configured)
right at the beginning of the simulation to give a brief overview of the actual NEORV32 SoC and CPU configurations.

[source, bash]
----
neorv32/sw/example/hello_world$ make USER_FLAGS+=-DUART0_SIM_MODE clean_all sim
Expand Down Expand Up @@ -208,39 +165,3 @@ Hello world! :)
<5> List of (default) arguments that were send to the simulator. Here: maximum simulation time (10ms).
<6> "Sanity checks" from the core's VHDL files. These reports give some brief information about the SoC/CPU configuration (-> generics). If there are problems with the current configuration, an ERROR will appear.
<7> Execution of the actual program starts.


:sectnums:
=== Advanced Simulation using VUnit

https://vunit.github.io/[VUnit] is an open source unit testing framework for VHDL/SystemVerilog.
It allows continuous and automated testing of HDL code by complementing traditional testing methodologies.
The motto of VUnit is _"testing early and often"_ through automation.

VUnit is composed by a http://vunit.github.io/py/ui.html[Python interface] and multiple optional
http://vunit.github.io/vhdl_libraries.html[VHDL libraries].
The Python interface allows declaring sources and simulation options, and it handles the compilation, execution and
gathering of the results regardless of the simulator used.
That allows having a single `run.py` script to be used with GHDL, ModelSim/QuestaSim, Riviera PRO, etc.
On the other hand, the VUnit's VHDL libraries provide utilities for assertions, logging, having virtual queues, handling CSV files, etc.
The http://vunit.github.io/verification_components/user_guide.html[Verification Component Library] uses those features
for abstracting away bit-toggling when verifying standard interfaces such as Wishbone, AXI, Avalon, UARTs, etc.

Testbench sources in `sim` (such as `sim/neorv32_tb.vhd` and `sim/uart_rx*.vhd`) use VUnit's VHDL libraries for testing
NEORV32 and peripherals.
The entry-point for executing the tests is `sim/run.py`.

[source, bash]
----
# ./sim/run.py -l
neorv32.neorv32_tb.all
Listed 1 tests

# ./sim/run.py -v
Compiling into neorv32: rtl/core/neorv32_uart.vhd passed
Compiling into neorv32: rtl/core/neorv32_twi.vhd passed
Compiling into neorv32: rtl/core/neorv32_trng.vhd passed
...
----

See http://vunit.github.io/user_guide.html[VUnit: User Guide] and http://vunit.github.io/cli.html[VUnit: Command Line Interface] for further info about VUnit's features.
24 changes: 0 additions & 24 deletions sim/README.md

This file was deleted.

4 changes: 2 additions & 2 deletions sim/simple/ghdl.run.sh → sim/ghdl.run.sh
100755 → 100644
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@ done

GHDL="${GHDL:-ghdl}"

$GHDL -m --work=neorv32 --workdir=build neorv32_tb_simple
$GHDL -m --work=neorv32 --workdir=build neorv32_tb

if [ -z "$1" ]
then
Expand All @@ -32,7 +32,7 @@ fi

echo "Using simulation run arguments: $GHDL_RUN_ARGS";

runcmd="$GHDL -r --work=neorv32 --workdir=build neorv32_tb_simple \
runcmd="$GHDL -r --work=neorv32 --workdir=build neorv32_tb \
--max-stack-alloc=0 \
--ieee-asserts=disable \
--assert-level=error $GHDL_RUN_ARGS"
Expand Down
6 changes: 3 additions & 3 deletions sim/simple/ghdl.setup.sh → sim/ghdl.setup.sh
100755 → 100644
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ set -e

cd $(dirname "$0")

NEORV32_LOCAL_RTL=${NEORV32_LOCAL_RTL:-../../rtl}
NEORV32_LOCAL_RTL=${NEORV32_LOCAL_RTL:-../rtl}

FILE_LIST=`cat $NEORV32_LOCAL_RTL/file_list_soc.f`
CORE_SRCS="${FILE_LIST//NEORV32_RTL_PATH_PLACEHOLDER/"$NEORV32_LOCAL_RTL"}"
Expand All @@ -16,5 +16,5 @@ ghdl -i --work=neorv32 --workdir=build \
"$NEORV32_LOCAL_RTL"/processor_templates/*.vhd \
"$NEORV32_LOCAL_RTL"/system_integration/*.vhd \
"$NEORV32_LOCAL_RTL"/test_setups/*.vhd \
neorv32_tb.simple.vhd \
uart_rx.simple.vhd
neorv32_tb.vhd \
uart_rx.vhd
12 changes: 12 additions & 0 deletions sim/ghdl.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
#!/usr/bin/env bash

# Abort if any command returns != 0
set -e

cd $(dirname "$0")

# Setup simulation
/bin/bash ghdl.setup.sh

# Run simulation (pass down more than 1 parameter to GHDL)
/bin/bash ghdl.run.sh $@
Loading