# VeeR-ISS **Repository Path**: gdwindow/VeeR-ISS ## Basic Information - **Project Name**: VeeR-ISS - **Description**: Whisper is a RISC-V instruction set simulator (ISS) developed for the verification of the Veer micro-controller. It allows the user to run RISC-V code without RISC-V hardware. It has an interactive mo - **Primary Language**: C++ - **License**: Apache-2.0 - **Default Branch**: main - **Homepage**: None - **GVP Project**: No ## Statistics - **Stars**: 0 - **Forks**: 2 - **Created**: 2024-04-29 - **Last Updated**: 2024-04-29 ## Categories & Tags **Categories**: Uncategorized **Tags**: None ## README # Introduction Whisper is a RISC-V instruction set simulator (ISS) developed for the verification of the Veer micro-controller. It allows the user to run RISC-V code without RISC-V hardware. It has an interactive mode where the user can single step the target RISC-V code and inspect/modify the RISC-V registers or the simulated system memory. It can also run in lock step with a Verilog simulator serving as a "golden model" against which an implementation is checked after each instruction of a test program. # Requirements To use Whisper, you would need to download its source code, compile it, prepare some target test program, compile the test program to RISCV binary code and then run the RISCV binary within the Whisper simulator. In particular you would need: 1. A Linux machine to host the RISCV tool-chain and Whisper. 2. The RISC-V toolchain which contains a cross-compiler to compile C/C++ code to a RISC-V binary. This can be installed on most Linux distributions using your distro's pacakge manager (apt, dnf, pacman etc.) Otherwise it can be built from the upstream source code. Ubuntu: ```shell sudo apt install gcc-riscv64-unknown-elf ``` Arch: ```shell sudo pacman -Syu riscv64-elf-gcc ``` 3. The Whisper source code which can be downloaded from [github](https://github.com/chipsalliance/VeeR-ISS). 4. The g++ compiler version >= 7.2 is needed to compile Whisper. The g++ compiler can be installed from a Linux distribution. Alternatively, the source code can be downloaded from [gnu.org/software/gcc](https://www.gnu.org/software/gcc). 5. The boost library version 1.67 of higher compiled with c++-14 or c++-17. Boost source can be downloaded from [boost.org](https://www.boost.org). # Compiling Whisper On a Unix system, in the `whisper` directory, do the following: ```shell make BOOST_DIR=
...
Disassemble opcodes. Example: disass opcode 0x3b 0x8082
disass function
Disassemble function with given name. Example: disass func main
disass >
Disassemble memory locations between addr1 and addr2.
elf file
Load elf file into simulated memory.
hex file
Load hex file into simulated memory.
replay_file file
Open command file for replay.
replay n
Execute the next n commands in the replay file or all the
remaining commands if n is missing.
replay step n
Execute consecutive commands from the replay file until n
step commands are executed or the file is exhausted.
reset []
Reset hart. If reset_pc is given, then change the reset program
counter to the given reset_pc before resetting the hart.
quit
Terminate the simulator.
## Newlib Emulation
Whisper will emulate the newlib open, close, read, write, brk and exit
system calls. This allows simple programs to run and use the newlib C-library
functions such as printf, fopen, fread, fwrite, fclose, malloc,
free and exit. Here an example of running a program with limited
C-library support:
```shell
whisper --newlib test3
```
And here is an example of passing the command line arguments arg1 and arg2
to the to the target program test3:
```shell
whisper --newlib "test3 arg1 arg2"
```
And examples of passing command line switches to a target program
that requires them:
```shell
whisper --newlib "test4 -opt1 val1 -opt2"
whisper --newlib --target "test4 -opt1 val1 -opt2"
```
# Debugging RISCV Programs Using GDB and Whisper
With the --gdb option, whisper will follow the gdb remote debugging
protocol. This allows the user to debug a RISCV program using a
cross-compiled gdb and whisper. For example, to debug a RISCV program
named `xyz` on a Linux x86 machine, we would start the (cross-compiled)
RISCV gdb as follows:
```shell
riscv-unknown-elf-gdb xyz
```
at the gdb prompt, we would connect to whisper by issuing a "target remote"
gdb command as follows:
```
target remote | whisper --gdb xyz
```
# Configuring Whisper
A JSON configuration file may be specified on the command line using the
`--configfile` switch. Numeric parameters may be specified as integers or
as strings. For example, a core count of 4 may be specified as:
```
"cores" : 4
```
or
```
"cores" : "4"
```
If expressed as a string, a numeric value may be prefixed with 0x to
specify headecimal notation (JSON does not support hexadecimal notation
for integers).
The value of a boolean parameters may be specified as an integer with 0
indicating false and non-zero indicating true. Alternatively it may
be specified using the strings "false", "False", "true", or "True".
Command line options override settings in the configuration file.
Here is a sample configuration file:
```json
{
"xlen" : 32,
"enable_zfh" : "true",
"enable_zba" : "true",
"enable_zbb" : "true",
"abi_names" : "true",
"csr" : {
"misa" : {
"reset-comment" : "imabfv",
"reset" : "0x40201123",
"mask-comment" : "Misa is not writable by CSR instructions",
"mask" : "0x0"
},
"mstatus" : {
"mstatus-comment" : "Hardwired to zero except for FS, VS, and SD.",
"reset" : "0x80006600",
"mask" : "0x0",
"poke_mask" : "0x0"
}
}
}
```
## Configuration parameters
### cores
Number of cores in simulated system.
### xlen
Integer register size in bits.
### memmap
Object defining memory organization. Fields of memap:
* `size`: Field defining physical memory size
* `page_size`: Field defining page size
* `inst`: Array of entries defining areas of physical memory where
instruction fetch is legal (if not used, then all of memory is valid
for fetch). Each entry is an array of 2 integers defining the start
and end address of a fetch region.
* `data`: Array of entries defining areas of physical memory where
data load/store is legal (if not used, then all of memory is
valid for load/store). Each entry is an array of 2 integers
defining the start and end address of a data region.
Example:
```json
"memmap" : { "size" : "0x100000000", "page_size" : 4096,
"inst" : [0, "0x20000000"] }
```
##### internal and external memory mapped registers
A memory region may be a memory-mapped register (e.g. PIC/PLIC/CLINT) of arbitrary size.
In json file you can define multiple memory-mapped-register regions
each has its own base address and size and an indication if the region
is *internal* or *external*. In addition, there is a single map for all
implemented registers in all regions, each register has name, count,
size and mask. An unimplemented register has mask=0.
Access to memory-map-register region either for implemented or unimplemented
register must be aligned to register size (default 4) and access size must
be equals to register size
Example:
```json
"memory_mapped_registers" : {
"default_mask" : 0,
"address" : [
"0x8000000",
"0x4000000"
],
"size" : [
65536,
67108864
],
"internal" : "false",
"registers" : {
"meip" : {
"count" : 31,
"address" : "0x4001000",
"mask" : "0x0"
},
"meipl" : {
"count" : 31,
"address" : "0x4000004",
"mask" : "0xf"
},
"mtime" : {
"count" : 1,
"address" : "0x800bff8",
"size" : 8,
"mask" : "0xffffffffffffffff"
}
}
}
```
### num_mmode_perf_regs
Number of implemented performance counters. If the specified number is n,
then CSRs (counters) mhpmcounter3 to mhpmcounter3+n-1 are implemented
and the remaining counters are hardwired to zero. Same for the
mhpmevent CSRs.
### enable_performance_counters
Whisper will count events associated with performance counters when
this is set to true. Note that pipeline specific events (such as
mispredicted branches) are not supported. Synchronous events (such as
count retired load insructions) are supported.
### abi_names
If set to true then registers are identified by their ABI names in the
log file (e.g. `ra` instead of `x1`).
### csr
The CSR configuration is a map wher each key is a CSR name and the
corresponding value is an object with the following fields: `number`,
`reset`, `mask`, `poke_mask`, `exists`, and `shared`. Set `exists` to
`false` to mark a non implemented CSR (read/write instructions to such a
CSR will trigger illegal instruciton exception). Set `mask` to the
write mask of the CSR (zero bits correspond to bits that will be
preserved by write instructions). Set `reset` to reset value of the
CSR. Set `shared` to `true` for CSRs that are shared between harts. The
`number` fields should be used to define the number (address) of a
non-standard CSR. The poke_mask should be used for the rare cases
where poke operation may modify some bits that are not modifiable by
CSR write instructions.
### vector
The vector configuration is an object with the following fields:
* `bytes_per_vec`: vector size in bytes
* `min_bytes_per_elem`: narrowest suppoted element size in bytes (default 1).
* `max_bytes_per_elem`: widest supported element size in bytes (no default).
Example:
```json
"vector" : {
"bytes_per_vec" : 16,
"max_bytes_per_elem" : 8
}
```
### reset_vec
Defines the PC value after reset
### nmi_vec
Defines the PC address after a non-maskable-interrupt.
### enable_triggers
Enable support for debug triggers.
# Limitations
The MISA register is read only. It is not possible to change XLEN at
run time by writing to the MISA register.
The "round to nearest break tie to max magnitude" rounding mode is not
implemented unless you compile with the softfloat library: `make
SOFT_FLOAT=1` in which case simulation of floating point instructions
slows down significantly.
Suppprted extensions: A, B, C, D, F, I, M, S, U, V, ZFH, ZBA, ZBB, and ZBS.