Skip to content

Commit

Permalink
Merge pull request riscv-verification#1 from riscv-verification/aidan…
Browse files Browse the repository at this point in the history
…/tidyup

Add include/source folders and tidy up
  • Loading branch information
eroom1966 committed Jan 4, 2022
2 parents 7e9625a + c7c9747 commit f113aaf
Show file tree
Hide file tree
Showing 8 changed files with 287 additions and 189 deletions.
111 changes: 84 additions & 27 deletions README.md
Expand Up @@ -3,70 +3,127 @@

This is a work in progress.

About
-----
When verifying RISC-V CPU RTL in a Verilog simulator, interfaces are needed between the core RTL, the test bench, and the other verification components.
## About

Each RISC-V core being designed so far has implemented its own specific bespoke interfaces for the specific core and the various verification components, and has required a specific bespoke test bench. This means with each design, all components, and testbench having their own custom interfaces there is very little re-use that can be made and the process is inefficient and time consuming. More effort goes into testing than design and so it is essential going forward to make the hardware design verification (HW DV) process as efficient as possible.
When verifying RISC-V CPU RTL in a Verilog simulator, interfaces are needed
between the core RTL, the test bench, and other verification components.

The RISC-V Verification Interface (RVVI) is a draft open standard that defines several of the interfaces required to bring together several of the subsystems required for RISC-V processor DV.
Each RISC-V core being designed so far has implemented its own specific bespoke
interfaces for the specific core and the various verification components, and
has required a specific bespoke test bench. This means with each design, all
components, and testbench having their own custom interfaces there is very
little re-use that can be made and the process is inefficient and time
consuming. More effort goes into testing than design and so it is essential
going forward to make the hardware design verification (HW DV) process as
efficient as possible.

By adopting these standards, components can be created that can be re-used across different design teams within a company, across different companies, and also for open source components to be developed, made available, and be included easily.
The RISC-V Verification Interface (RVVI) is a draft open standard that defines a
number of interfaces required to bring together several of the subsystems
required for RISC-V processor DV.

Of course, if DV components use these standards as they are developed for one design, they can be easily used for subsequent designs in one team.
By adopting these standards, components can be created that can be re-used
across different design teams within a company, across different companies, and
also for open source components to be developed, made available, and be included
easily.

Of course, if DV components use these standards as they are developed for one
design, they can be easily used for subsequent designs in one team.

In short, standards such as RVVI make re-use possible for RISC-V processor DV.

Use of RVVI is not just of benefit for test bench re-use but also for test generators, functional coverage, and other testing methodologies.
Use of RVVI is not just of benefit for test bench re-use but also for test
generators, functional coverage, and other testing methodologies.

Currently there are 3 different areas that RVVI addresses:

The core (Device Under Test) RTL Verilog interface - RVVI-VLG

-----
First is the interface to the internals of the RTL of the core's micro-architecture to provide values, state, and events related to the internal signals up to several of the testbench components. Traditionally this was done to provide tracing capabilities such as for log file writing. In the past, this interface or similar has been used to create a 'tracer'.
## The core (Device Under Test) RTL Verilog interface - RVVI-VLG

The RVVI-VLG interface includes capabilities for use with simple single hart in-order cores to multi-hart, multi-issue, Out-of-Order, cores with asynchronous interrupts, and debug modes etc.
First is the interface to the internals of the RTL of the core's
micro-architecture to provide values, state, and events related to the internal
signals up to several of the testbench components. Traditionally this was done
to provide tracing capabilities such as for log file writing. In the past, this
interface or similar has been used to create a 'tracer'.

The RVVI-VLG interface includes capabilities for use with simple single hart
in-order cores to multi-hart, multi-issue, Out-of-Order, cores with asynchronous
interrupts, and debug modes etc.

The RVVI-VLG interface is defined in SystemVerilog.

The reference model DV subsystem interface - RVVI-API

-----
To verify a RISC-V core requires comparison of the Device Under Test (DUT) against a reference model. This is not as simple as just running programs on the reference and DUT and comparing PC values - it needs to take into account all ISA architectural features and options including full asynchronous operation.
## The reference model DV subsystem interface - RVVI-API

The RVVI-API interface is a set of API function calls that abstract away many of the details of the operation of processor reference models and decouples the test bench from any specific reference model.
To verify a RISC-V core requires comparison of the Device Under Test (DUT)
against a reference model. This is not as simple as just running programs on the
reference and DUT and comparing PC values - it needs to take into account all
ISA architectural features and options including full asynchronous operation.

The RVVI-API is a C/C++ API and can be used with C/C++ test benches. RVVI-API also is defined with a SystemVerilog DPI wrapper to be used in SystemVerilog test benches.
The RVVI-API interface is a set of API function calls that abstract away many of
the details of the operation of processor reference models and decouples the
test bench from any specific reference model.

The RVVI-API is a C/C++ API and can be used with C/C++ test benches. RVVI-API
also is defined with a SystemVerilog DPI wrapper to be used in SystemVerilog
test benches.


The common Virtual Periherals used in the test bench - RVVI-VPI
-----
When testing a processor there are components needed in the test bench to interact with the processor - for example a virtual UART to print information from the program operation, and timers to generate asynchronous interrupts.
## The common Virtual Periherals used in the test bench - RVVI-VPI

When testing a processor there are components needed in the test bench to
interact with the processor - for example a virtual UART to print information
from the program operation, and timers to generate asynchronous interrupts.

These components are being defined so that they can be used in C/C++, SystemVerilog, test benches, and also in some cases within ISS - to allow ease of test creation.
These components are being defined so that they can be used in C/C++,
SystemVerilog, test benches, and also in some cases within ISS - to allow ease
of test creation.

This RVVI-VPI is currently a work in progress and is looking cover: timers,
interrupts, debug, random event generators, and printer/log/UART capabilities.

This RVVI-VPI is currently a work in progress and is looking cover: timers, interrupts, debug, random event generators, and printer/log/UART capabilities.

History
-------
This work has evolved from the experience by Imperas, EMMicro, and SiLabs working with several RISC-V verification projects including its collaboration in OpenHW Group (https://github.com/openhwgroup/core-v-verif) on the Core-V range of open-source RISC-V cores.
## History

This work has evolved from the experience by Imperas, EMMicro, and SiLabs
working with several RISC-V verification projects including collaboration with
OpenHW Group (https://github.com/openhwgroup/core-v-verif) on the Core-V range
of open-source RISC-V cores.

There is the RISC-V Formal Interface (RVFI)
(https://github.com/SymbioticEDA/riscv-formal) from SymbioticEDA which is a very
good interface for providing observation into a running core by streaming what
is executing on the core (i.e. the basic tracer funtionality) - but for quality
RISC-V processor DV more is needed. Hence the need for RVVI. The RVVI-VLG
interface has some parts very similar to the RVFI formal interface and RVVI can
be thought of as a superset of RVFI.

There is the RISC-V Formal Interface (RVFI) (https://github.com/SymbioticEDA/riscv-formal) from SymbioticEDA which is a very good interface for providing observation into a running core by streaming what is executing on the core (i.e. the basic tracer funtionality) - but for quality RISC-V processor DV more is needed. Hence the need for RVVI. The RVVI-VLG interface has some parts very similar to the RVFI formal interface and RVVI can be thought of as a superset of RVFI.

Specifications
-------------
The specification of the interfaces can be found in different directories of this repository.
## Specifications

The specification of the interfaces can be found in different directories of
this repository.

[RVVI-VLG Verilog](RVVI-VLG)

[RVVI-API referance model subsystem API](RVVI-API)

[RVVI-VPI Virtual Periheral Inrerface](RVVI-VPI)

Implementations and usage

--------------
[Imperas](https://www.imperas.com/imperasdv) provides examples of use of RVVI with its ImperasDV product with C/C++ for Verilator designs and SystemVerilog for use with Xcelium, VCS, Questa from Cadence, Synopsys, Siemens EDA respectively.
## Implementations and usage

[OpenHW](https://www.openhwgroup.org/) are using RVVI in its [CV32E40X](https://github.com/openhwgroup/core-v-verif/tree/master/cv32e40x) open source SystemVerilog test bench.
[Imperas](https://www.imperas.com/imperasdv) provides examples of use of RVVI
with its ImperasDV product with C/C++ for Verilator designs and SystemVerilog
for use with Xcelium, VCS, Questa from Cadence, Synopsys, Siemens EDA
respectively.

##
[OpenHW](https://www.openhwgroup.org/) are using RVVI in its
[CV32E40X](https://github.com/openhwgroup/core-v-verif/tree/master/cv32e40x)
open source SystemVerilog test bench.
53 changes: 35 additions & 18 deletions RVVI-API/README.md
@@ -1,22 +1,27 @@
# RVVI-API
# RVVI-API RISC-V Verification Interface

This repository contains a draft of RVVI-API, a standard interface for lockstep comparison between two RISC-V models for DV purposes.
This repository contains a draft of RVVI-API, a standard interface for lockstep
comparison between two RISC-V models for DV purposes.


----
# Overview

The RVVI-API is defined and is provided here as a header file and can be found in the following location:
- [include/host/rvvi/rvvi-api.h](include/host/rvvi/rvvi-api.h) C/C++
- [include/host/rvvi/rvvi-api.svh](include/host/rvvi/rvvi-api.svh) SystemVerilog
The RVVI-API is defined and is provided here as a header file and can be found
in the following location:
- [/include/host/rvvi/rvvi-api.h](../include/host/rvvi/rvvi-api.h) C/C++
- [/include/host/rvvi/rvvi-api.svh](../include/host/rvvi/rvvi-api.svh)
SystemVerilog

The diagram below shows a simplified sequence diagram of the RVVI-API interface and how each of the three pieces of a verification environment interface.
The diagram below shows a simplified sequence diagram of the RVVI-API interface
and how each of the three pieces of a verification environment interface.

![Overview Image](/RVVI-API/images/overview.jpg)

The test harness shown in the center is in charge of coordinating the sequence of events during testing.
The DUT shown on the left will primarily be a RISC-V core written in Verilog.
The reference model on the right is more complex and consists of a number of distinct elements:
The test harness shown in the center is in charge of coordinating the sequence
of events during testing. The DUT shown on the left will primarily be a RISC-V
core written in Verilog. The reference model on the right is more complex and
consists of a number of distinct elements:
- A golden reference model with all the required features and accuracy.
- A mirror of the DUT state, which is updated via the `rvvi...Set` functions.
- A comparator module which can compare the simulator and mirrored DUT state.
Expand All @@ -27,22 +32,34 @@ There are three main phases a harness will be in charge of:
- Shutdown

The initialization phase is as follows:
- The test harness first initializes the DUT supplying a path to a test case ELF file.
- The reference subsystem will be initialized, again supplying a path to the same test case ELF file.
- The test harness first initializes the DUT supplying a path to a test case ELF
file.
- The reference subsystem will be initialized, again supplying a path to the
same test case ELF file.
- The reference subsystem is informed of any configuration options.

The main loop then begins which will continue until either the terminal state is encountered (pass) or a mismatch is detected (fail). The loop is generally constructed as follows:
The main loop then begins which will continue until either the terminal state is
encountered (pass) or a mismatch is detected (fail). The loop is generally
constructed as follows:
- The DUT model is requested to step until an event occurs.
- During this call, the DUT will inform the harness of any state changes.
- The harness will then forward the state changes to the reference model.
- The harness then asks the reference model to step until it encounters the next event.
- After both models have stepped, the harness asks the reference model to compare its state with that of is mirror of the DUT state.
- Simulation will end if a mismatch occurs or both models reached a terminal state, otherwise the main loop will continue.
- The harness then asks the reference model to step until it encounters the next
event.
- After both models have stepped, the harness asks the reference model to
compare its state with that of is mirror of the DUT state.
- Simulation will end if a mismatch occurs or both models reached a terminal
state, otherwise the main loop will continue.

The shutdown phase is very simple, giving both models a change to release any resources they may have been using.
The shutdown phase is very simple, giving both models a change to release any
resources they may have been using.
- The harness will issue a shutdown command to the DUT.
- The harness will issue a shutdown command to the Reference model.

Note: In this context, an event is considered an instruction retirement or a exception being raised.
Note: In this context, an event is considered an instruction retirement or a
exception being raised.

Note: The harness is also free to inspect the DUT state changes that are received via the `rvvi...Get` callbacks to decide if testing should halt. This would allow certain instruction sequences or memory access patterns be used as a signal to halt testing.
Note: The harness is also free to inspect the DUT state changes that are
received via the `rvvi...Get` callbacks to decide if testing should halt. This
would allow certain instruction sequences or memory access patterns be used as a
signal to halt testing.
99 changes: 97 additions & 2 deletions RVVI-VLG/README.md
@@ -1,3 +1,98 @@
# RISC-V Verification Interface (RVVI)
# RVVI-VLG RISC-V Verification Interface

Please refer to this document: [rvvi-vlg.md](rvvi-vlg.md)
This is a work in progress

# Overview
----
The following specification defines a method of observing a RISCV
implementation. Observation is required for the internal state, in addition to
asynchronous event changes on items such as Interrupts and Debug.

The RVVI-VLG interface implementation can be found in the following location:
- [/source/host/rvvi/rvvi-vlg.sv](../source/host/rvvi/rvvi-vlg.sv)


# RVVI-VLG Interface
----
This interface provides internal visibility of the state of the RISC-V device.
It also provides a notifier event to indicate a change of state, following a
data change. All signals on the RVVI_state interface are outputs from the
device, for observing state transitions and state values.

### notify
- This event indicates some change of state following the completion of an
event. An event can either be an instruction (or many instructions) retiring,
or an instruction (or many instructions) causing an exception. When the notify
event is asserted, the signals, valid, trap and halt indicate the current
state at this notification event point.

- Dependant upon how many instructions can retire (`NRET`) in a single cycle,
each of the following variables are sized (in width) by that NRET value, so if
the architecture is able to retire 4 instructions within a single cycle, then
the width of these variable is [4]. In addition the variables are also sized
by the number of harts being handled through the interface.

### valid
- When this signal is true at a notify event, an instruction has been
successfully retired by the device, subsequent internal state values will have
been updated accordingly, this includes the Integer/GPR, Float/FPR, Vector/VR
CSR and any other supported registers. The instruction address retired is
indicated by the pc_rdata variable.

### trap
- When this signal is true at a notify event, an instruction execution has
undergone an exception for some reason, this could include
synchronous/asynchronous exception, or a debug request. This event allows the
reading of internal state. The instruction address trapped is indicated by the
`pc_rdata` variable.

### halt
- When this signal is true at a notify event, it indicates that the hart has
gone into a halted state at this instruction.

### intr
- When this signal is true at a notify event, it indicates that this retired
instruction is the first instruction which is part of a trap handler.

### order
- This signal contains the instruction count for the instruction being reported
at the notifier event.

### insn
- This signal contains the instruction word which is at the trap or valid event.

### isize
- The size of the instruction held in insn, this should be either 2(compressed)
or 4(uncompressed).

### mode
- This signal indicates the operating mode (Machine, Supervisor, User).

### ixl
- This signal indicates the current `XLEN` for the given privilege mode of
operation.

### pc_rdata
- This is the address of the instruction at the trap or valid notify event.

### pc_wdata
- This is the address of the next instruction to be executed after a trap or
valid notify event.

### x_addr, x_wdata, x_wb
- If `x_wb` is true, then an X register writeback has occured, the index is
indicated by `x_addr` the value is indicated by `x_wdata`.

### f_addr, f_wdata, f_wb
- If `f_wb` is true, then an F/D register writeback has occured, the index is
indicated by `f_addr` and value is indicated by `f_wdata`.

### v_addr, v_wdata, v_wb
- If `v_wb` is true, then a V register writeback has occured, the index is
indicated by `v_addr` and value is indicated by `v_wdata`.

### csr, csr_wb
- If the bit position within `csr_wb` is true, then a the position indicates a
write into csr, eg if `csr_wb=0x1`, then the ustatus register (address 0x000)
has been written. If `csr_wb=(1<<4 | 1<<0)` then address 0x004 and 0x001 have
been written concurrently csr_wb=0x0 indicates no written csr.

0 comments on commit f113aaf

Please sign in to comment.