Skip to content

mariusmm/RISC-V-TLM

Repository files navigation

Another RISC-V ISA simulator.

This code is suitable to hard refactor at any time

This is another RISC-V ISA simulator, this is coded in SystemC + TLM-2. It supports RV32IMAC and RV64IMAC Instruction set.

travis Codacy Badge Coverity Scan Build Status license last commit commit activity Docker Twitter URL DOI


Table of Contents

Description

Brief description of the modules:

  • CPU: Top entity that includes all other modules.
  • Memory: Memory highly based on TLM-2 example with read file capability
  • Registers: Implements the register file, PC register & CSR registers
  • Instruction: Decodes instruction type and keeps instruction field
  • BASE_ISA: Executes Base ISA, Zifencei and Zicsr.
    • C_extension: Decodes & Executes Compressed instructions (C extension)
    • M_extension: Decodes & Executes Multiplication and Division instructions (M extension)
    • A_extension: Decodes & Executes Atomic instructions (A extension)
  • Simulator: Top-level entity that builds & starts the simulation
  • BusCtrl: Simple bus manager
  • Trace: Simple trace peripheral
  • Timer: Simple IRQ programable real-time counter peripheral
  • Debug: GDB server for remote debugging (Beta)

Helper classes:

  • Performance: Performance indicators stores here (singleton class)
  • Log: Log class to log them all (singleton class)

Current performance is about 3.000.000 instructions / sec in a Intel Core i5-5200@2.2Ghz and about 4.500.000 instructions / sec in a Intel Core i7-8550U@1.8Ghz.

Trace perihperal creates a xterm window where it prints out all received data.

Structure

Modules' hierarchy

Memory map

Base Module Description
0x40000000 Trace Output data to xterm
0x40004000 Timer LSB Timer
0x40004004 Timer MSB Timer
0x40004008 Timer MSB Timer Comparator
0x4000400C Timer LSB Timer Comparator

TODO

This is a preliminar and incomplete version.

Task to do:

  • Implement all missing instructions (Execute)
  • Implement CSRs (where/how?)
  • Add full support to read file with memory contents (to memory.h)
    • .elf files
    • .hex files (only partial .hex support)
  • Connect some TLM peripherals
    • Debug module similiar to ARM's ITM
    • Some standard UART model
    • ...
  • Implement interrupts
    • implement timer (mtimecmp) & timer interrupt
    • generic IRQ comtroller
  • Test, test, test & test. I'm sure there are a lot of some bugs in the code
    • riscv-test almost complete (see Test)
    • riscv-compliance
  • Improve structure and modules hierarchy
  • Add 64 architecture (RV64I)
  • Debug capabilities
  • Add Trace v2.0 support
  • Support to SystemC 3.0.0

Compile

In order to compile the project you need SystemC-2.3.3/4 installed in your system, and Boost Library Headers.

# Following Environment are needed to configure the project
export SYSTEMC_HOME=<Path to SystemC Library Installation>
# Check the SystemC Installation path for this setting
export LD_LIBRARY_PATH=$SYSTEMC_HOME/lib-linux64
# Optional BOOST_ROOT if not specified one should have Boost Header Package Installed
export BOOST_ROOT=<Path to extracted boost library sources>
# Clone the repo with submodules initialized
git clone --recurse-submodules https://github.com/mariusmm/RISC-V-TLM.git

# If already cloned one need to run the following command to initialize the git submodule from within the RISC-V-TLM cloned directory
git submodule update --init --recursive
# Configure, Build and deploy spdlog dependency
cd spdlog
# Configure spdlog submodule
cmake -H. -B_builds -DCMAKE_INSTALL_PREFIX=install -DCMAKE_BUILD_TYPE=Release
# Build spdlog
cmake --build _builds --config Release
# Install spdlog
cmake --build _builds --target install
cd ..
# Setup SPDLOG_HOME to point to spdlog dependency installation path for the built library, here PWD is the RISC-V-TLM project cloned directory
export SPDLOG_HOME=$PWD/spdlog/install

Then, you need to modifiy your LD_LIBRARY_PATH environtment variable to add path systemc library. In my case:

export LD_LIBRARY_PATH=/home/marius/Work/RiscV/code/systemc-2.3.2/lib-linux64

And then you can execute the simulator:

./RISCV_TLM asm/BasicLoop.hex

Using cmake

It is possible to use cmake:

# Create and cd into the build directory for RISC-V-TLM project
mkdir build
cd build
# Configure the project using CMake
cmake -DCMAKE_BUILD_TYPE=Release ..
# For additional configuration one can refer the CMake documentation on additional configuration options.
make

note that SystemC must be compiled with cmake:

cd <systemc directory>
mkdir build
cd build
cmake ../ -DCMAKE_CXX_STANDARD=17
make

Arguments

-L loglevel: 3 for detailed (INFO) log, 0 to ERROR log level

-f filename .hex binary filename to use

-D Enter in Debug mode, simulator starts gdb server (Beta)

-R 32 or 64 to choose 32-bit or 64-bit architecture

Cross-compiler

It is possible to use gcc as risc-v compiler. Follow the instructions (from https://github.com/riscv/riscv-gnu-toolchain):

git clone --recursive https://github.com/riscv/riscv-gnu-toolchain
cd riscv-gnu-toolchain
./configure --prefix=/opt/riscv --with-arch=rv32gc --with-abi=ilp32
make
# ...
# wait for long time ...
# ...
export PATH=$PATH:/opt/riscv/bin

In test/C/long_test/ example there is a Makefile that compiles a project with any .c files and links them against new-lib nano. There is a Helper_functions.c file with defiitions of all missing functions needed by the library (_read(), _close(), _fstat_r(), _lseek_r(), _isatty_r(), _write()). All of them are defined empty except _write() that is written to use the Trace perihperal. The definition of the function _write() allows developer to use printf() as usual and the stdout will be redirected to the Trace perihperal.

Debug

It is possible to debug an application running in RISC-V-TLM simulator. It is tested with riscv32-unknown-elf-gdb version 8.3.0.20190516-git and eclipse. Configure a "C/C++ Remote Application" debug configuration as the figure

Modules' hierarchy

gdbinit.txt file must contain:

set debug remote 1
set arch riscv:rv32

With this configuration, eclipse debuggins is almost normal (I experienced some problems wiith "step-over" and "step-into" commands)

Docker container

There is a Docker container available with the latest release at https://hub.docker.com/r/mariusmm/riscv-tlm. This container has RISCV-TLM already build at /usr/src/riscv64/RISCV-TLM directory.

How to use Docker

docker pull mariusmm/riscv-tlm
docker run -v <path_to_RISCV-V-TLM>/:/tmp -u $UID -e DISPLAY=$DISPLAY --volume="/tmp/.X11-unix:/tmp/.X11-unix:rw"  -it mariusmm/riscv-tlm /bin/bash

./RISC-V-TLM/build/RISCV_TLM /tmp/<your_hex_file>

or you can call binary inside docker image directly:

docker run -v <path_to_RISCV-V-TLM>/:/tmp -u $UID -e DISPLAY=$DISPLAY --volume="/tmp/.X11-unix:/tmp/.X11-unix:rw"  -it mariusmm/riscv-tlm /usr/src/riscv64/RISC-V-TLM/RISCV_TLM /tmp/<your_hex_file>

I'm using docker image zmors/riscv_gcc to have a cross-compiler, I'm using both docker images this way:

# console1:
docker run -v /tmp:/PRJ -it zmors/riscv_gcc:1  bash

# cd /PRJ/func3
# make

# console2:
docker run -v /tmp:/tmp -u $UID -e DISPLAY=$DISPLAY --volume="/tmp/.X11-unix:/tmp/.X11-unix:rw" -it mariusmm/riscv-tlm /bin/bash

# Run following commands as root/su user
cd /usr/src/riscv64/RISC-V-TLM/ 
./RISCV-TLM /tmp/file.hex
# ...

or

# ...
# console 2:
docker run -v /tmp/tmp -it  mariusmm/riscv-tlm /usr/src/riscv64/RISC-V-TLM/RISCV_TLM /tmp/file.hex

Performance is not affected by running the simulator inside the container

Test

See Test page for more information.

In the asm directory there are some basic assembly examples.

I "compile" one file with the follwing command:

cd asm
riscv32-unknown-elf-as  EternalLoop.asm -o EternalLoop.o
riscv32-unknown-elf-ld EternalLoop.o -o EternalLoop.elf
riscv32-unknown-elf-objcopy -O ihex EternalLoop.elf EternalLoop.hex
cd ..
./RISCV_SCTLM asm/EternalLoop.hex

This example needs that you hit Ctr+C to stop execution.

C code

The C directory contains simple examples in C. Each directory contains an example, to compile it just:

make

and then execute the .hex file like the example before.

FreeRTOS

FreeRTOS can run in this simulator!

In test/FreeRTOS/ directory there is portable files (port.c, portmacro.c portasm.S) and main file (freertos_test.c) ported to this RISC-V model.

Documentation

The code is documented using doxygen. In the doc folder there is a Doxygen.cfg file ready to be used.

Contribute

There are several ways to contribute to this project:

  • Test
  • Pull request are welcome (see TODO list)
  • Good documentation
  • RTL-Level simulation

Authors and credits

RISC-V-TLM is managed by Màrius Montón.

If you find this code useful, please consider citing:

@inproceedings{montonriscvtlm2020,
        title = {A {RISC}-{V} {SystemC}-{TLM} simulator},
        booktitle = {Workshop on {Computer} {Architecture} {Research} with {RISC}-{V} ({CARRV 2020}),
        author = {Montón, Màrius},
        year = {2020}
}

Publications

I've published a paper describing the RISC-V simulator in CARRV 2020 conference (pdf).

License

Copyright (C) 2018, 2019, 2020, 2021, 2022 Màrius Montón (@mariusmonton)

This program is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version.

This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.

You should have received a copy of the GNU General Public License along with this program. If not, see http://www.gnu.org/licenses/.