Showing preview only (1,670K chars total). Download the full file or copy to clipboard to get everything.
Repository: agra-uni-bremen/riscv-vp
Branch: master
Commit: 48b2f5877b23
Files: 513
Total size: 1.5 MB
Directory structure:
gitextract_zs0_rad3/
├── .clang-format
├── .gitignore
├── .gitlab-ci.yml
├── .gitmodules
├── CITATION.cff
├── Dockerfile
├── LICENSE
├── Makefile
├── README.md
├── env/
│ └── basic/
│ └── vp-display/
│ ├── CMakeLists.txt
│ ├── VP-Display.pro
│ ├── framebuffer.h
│ ├── main.cpp
│ ├── mainwindow.cpp
│ ├── mainwindow.h
│ ├── mainwindow.ui
│ ├── vpdisplayserver.cpp
│ └── vpdisplayserver.h
├── sw/
│ ├── .gitignore
│ ├── Makefile
│ ├── Makefile.common
│ ├── README.md
│ ├── basic-asm/
│ │ ├── Makefile
│ │ └── sum.S
│ ├── basic-c/
│ │ ├── Makefile
│ │ ├── bootstrap.S
│ │ ├── main.c
│ │ └── sum.c
│ ├── basic-debug/
│ │ ├── Makefile
│ │ ├── bootstrap.S
│ │ ├── eclipse-remote-debug-readme.txt
│ │ ├── main.c
│ │ ├── remote-debug-readme.txt
│ │ └── test-ignore
│ ├── basic-dma/
│ │ ├── Makefile
│ │ ├── bootstrap.S
│ │ ├── irq.c
│ │ ├── irq.h
│ │ └── main.c
│ ├── basic-e/
│ │ ├── Makefile
│ │ └── sum.S
│ ├── basic-gcov/
│ │ ├── Makefile
│ │ └── test-ignore
│ ├── basic-gpio/
│ │ ├── Makefile
│ │ ├── bootstrap.S
│ │ ├── gpio.h
│ │ ├── link.ld
│ │ ├── main.c
│ │ ├── platform.h
│ │ ├── uart.c
│ │ ├── uart.h
│ │ ├── util.c
│ │ └── util.h
│ ├── basic-multicore/
│ │ ├── Makefile
│ │ ├── bootstrap.S
│ │ └── main.c
│ ├── blocking-sleep/
│ │ ├── Makefile
│ │ ├── bootstrap.S
│ │ ├── irq.S
│ │ └── main.c
│ ├── busy-wait-sleep/
│ │ ├── Makefile
│ │ ├── bootstrap.S
│ │ └── main.c
│ ├── c++-lib/
│ │ ├── Makefile
│ │ └── main.cpp
│ ├── clock-ticks/
│ │ ├── Makefile
│ │ ├── bootstrap.S
│ │ ├── irq.c
│ │ ├── irq.h
│ │ └── main.c
│ ├── crc8/
│ │ ├── Makefile
│ │ ├── bootstrap.S
│ │ ├── link.ld
│ │ ├── main.c
│ │ ├── platform.h
│ │ ├── uart.c
│ │ ├── uart.h
│ │ ├── util.c
│ │ └── util.h
│ ├── flashTest/
│ │ ├── Makefile
│ │ ├── main.cpp
│ │ └── test-ignore
│ ├── mramTest/
│ │ ├── Makefile
│ │ └── main.cpp
│ ├── mrv32-uart/
│ │ ├── Makefile
│ │ ├── bootstrap.S
│ │ ├── link.ld
│ │ ├── main.c
│ │ ├── platform.h
│ │ ├── uart.c
│ │ ├── uart.h
│ │ ├── util.c
│ │ └── util.h
│ ├── peripheral-in-the-loop/
│ │ ├── Makefile
│ │ └── main.c
│ ├── printf/
│ │ ├── Makefile
│ │ ├── entry.S
│ │ └── main.c
│ ├── simple-display/
│ │ ├── Makefile
│ │ ├── libDisplay.cpp
│ │ ├── libDisplay.hpp
│ │ ├── main.cpp
│ │ └── test-ignore
│ ├── simple-scheduler/
│ │ ├── Makefile
│ │ ├── cor.S
│ │ ├── main.c
│ │ └── no-clib/
│ │ ├── Makefile
│ │ ├── bootstrap.S
│ │ ├── cor.S
│ │ └── main.c
│ ├── simple-sensor/
│ │ ├── Makefile
│ │ ├── bootstrap.S
│ │ ├── irq.c
│ │ ├── irq.h
│ │ └── main.c
│ ├── sys-read/
│ │ ├── Makefile
│ │ ├── main.c
│ │ └── test-ignore
│ └── test.sh
└── vp/
├── .gitignore
├── CMakeLists.txt
├── cmake/
│ └── AddGitSubmodule.cmake
└── src/
├── CMakeLists.txt
├── core/
│ ├── CMakeLists.txt
│ ├── common/
│ │ ├── CMakeLists.txt
│ │ ├── bus_lock_if.h
│ │ ├── clint.h
│ │ ├── clint_if.h
│ │ ├── core_defs.h
│ │ ├── debug.h
│ │ ├── debug_memory.cpp
│ │ ├── debug_memory.h
│ │ ├── dmi.h
│ │ ├── elf_loader.h
│ │ ├── fp.h
│ │ ├── gdb-mc/
│ │ │ ├── CMakeLists.txt
│ │ │ ├── gdb_runner.cpp
│ │ │ ├── gdb_runner.h
│ │ │ ├── gdb_server.cpp
│ │ │ ├── gdb_server.h
│ │ │ ├── handler.cpp
│ │ │ ├── libgdb/
│ │ │ │ ├── CMakeLists.txt
│ │ │ │ ├── README.md
│ │ │ │ ├── include/
│ │ │ │ │ └── libgdb/
│ │ │ │ │ ├── parser1.h
│ │ │ │ │ ├── parser2.h
│ │ │ │ │ └── response.h
│ │ │ │ ├── internal.h
│ │ │ │ ├── parser1.c
│ │ │ │ ├── parser2.c
│ │ │ │ ├── parser2.h
│ │ │ │ ├── response.c
│ │ │ │ └── util.c
│ │ │ ├── register_format.cpp
│ │ │ └── register_format.h
│ │ ├── instr.cpp
│ │ ├── instr.h
│ │ ├── irq_if.h
│ │ ├── load_if.h
│ │ ├── mmu.h
│ │ ├── mmu_mem_if.h
│ │ ├── rawmode.cpp
│ │ ├── rawmode.h
│ │ ├── real_clint.cpp
│ │ ├── real_clint.h
│ │ ├── timer.cpp
│ │ ├── timer.h
│ │ └── trap.h
│ ├── rv32/
│ │ ├── CMakeLists.txt
│ │ ├── csr.h
│ │ ├── elf_loader.h
│ │ ├── iss.cpp
│ │ ├── iss.h
│ │ ├── mem.h
│ │ ├── mem_if.h
│ │ ├── mmu.h
│ │ ├── syscall.cpp
│ │ ├── syscall.h
│ │ ├── syscall_if.h
│ │ └── timing/
│ │ ├── timing_external.h
│ │ └── timing_simple.h
│ └── rv64/
│ ├── CMakeLists.txt
│ ├── csr.h
│ ├── elf_loader.h
│ ├── iss.cpp
│ ├── iss.h
│ ├── mem.h
│ ├── mem_if.h
│ ├── mmu.h
│ ├── syscall.cpp
│ ├── syscall.h
│ └── syscall_if.h
├── platform/
│ ├── CMakeLists.txt
│ ├── basic/
│ │ ├── CMakeLists.txt
│ │ ├── basic_timer.h
│ │ ├── display.cpp
│ │ ├── display.hpp
│ │ ├── dma.h
│ │ ├── ethernet.cpp
│ │ ├── ethernet.h
│ │ ├── flash.h
│ │ ├── main.cpp
│ │ ├── random_source.h
│ │ ├── sensor.h
│ │ └── sensor2.h
│ ├── common/
│ │ ├── CMakeLists.txt
│ │ ├── async_event.h
│ │ ├── bus.h
│ │ ├── fd_abstract_uart.cpp
│ │ ├── fd_abstract_uart.h
│ │ ├── fe310_plic.cpp
│ │ ├── fe310_plic.h
│ │ ├── fu540_plic.cpp
│ │ ├── fu540_plic.h
│ │ ├── memory.h
│ │ ├── memory_mapped_file.h
│ │ ├── options.cpp
│ │ ├── options.h
│ │ ├── slip.cpp
│ │ ├── slip.h
│ │ ├── terminal.h
│ │ ├── uart.cpp
│ │ ├── uart.h
│ │ ├── uart16550.h
│ │ ├── uart_if.cpp
│ │ ├── uart_if.h
│ │ └── util.h
│ ├── hifive/
│ │ ├── CMakeLists.txt
│ │ ├── aon.h
│ │ ├── can/
│ │ │ ├── 90-slcan.rules
│ │ │ ├── CAN-Howto.md
│ │ │ ├── cantest.cpp
│ │ │ ├── mcp_can_dfs.h
│ │ │ ├── slcan_add.sh
│ │ │ └── slcan_remove.sh
│ │ ├── can.cpp
│ │ ├── can.h
│ │ ├── gpio.cpp
│ │ ├── gpio.h
│ │ ├── hifive_main.cpp
│ │ ├── maskROM.h
│ │ ├── oled/
│ │ │ ├── common.cpp
│ │ │ ├── common.hpp
│ │ │ ├── oled.cpp
│ │ │ └── oled.hpp
│ │ ├── otp.h
│ │ ├── prci.h
│ │ ├── spi.h
│ │ ├── tunnel-uart.cpp
│ │ └── tunnel-uart.hpp
│ ├── hwitl/
│ │ ├── CMakeLists.txt
│ │ ├── main.cpp
│ │ ├── virtual_bus_tlm_connector.cpp
│ │ └── virtual_bus_tlm_connector.hpp
│ ├── linux/
│ │ ├── CMakeLists.txt
│ │ ├── linux_main.cpp
│ │ └── prci.h
│ ├── linux32/
│ │ ├── CMakeLists.txt
│ │ ├── linux32_main.cpp
│ │ └── prci.h
│ ├── microrv32/
│ │ ├── CMakeLists.txt
│ │ ├── main.cpp
│ │ ├── microrv32_gpio.h
│ │ ├── microrv32_led.h
│ │ └── microrv32_uart.h
│ ├── test32/
│ │ ├── CMakeLists.txt
│ │ ├── htif.h
│ │ └── test32_main.cpp
│ ├── tiny32/
│ │ ├── CMakeLists.txt
│ │ └── tiny32_main.cpp
│ ├── tiny32-mc/
│ │ ├── CMakeLists.txt
│ │ └── mc_main.cpp
│ ├── tiny64/
│ │ ├── CMakeLists.txt
│ │ └── tiny64_main.cpp
│ └── tiny64-mc/
│ ├── CMakeLists.txt
│ └── mc_main.cpp
├── util/
│ ├── common.h
│ ├── elegantEnums.cpp
│ ├── elegantEnums.hpp
│ ├── gtkwave_riscv-filter/
│ │ ├── .gitignore
│ │ ├── CMakeLists.txt
│ │ └── riscv-filter.cpp
│ ├── gtkwave_riscv-filter.py
│ ├── memory_map.h
│ ├── options.h
│ └── tlm_map.h
└── vendor/
├── CMakeLists.txt
└── softfloat/
├── CMakeLists.txt
├── f128_add.c
├── f128_classify.c
├── f128_div.c
├── f128_eq.c
├── f128_eq_signaling.c
├── f128_isSignalingNaN.c
├── f128_le.c
├── f128_le_quiet.c
├── f128_lt.c
├── f128_lt_quiet.c
├── f128_mul.c
├── f128_mulAdd.c
├── f128_rem.c
├── f128_roundToInt.c
├── f128_sqrt.c
├── f128_sub.c
├── f128_to_f16.c
├── f128_to_f32.c
├── f128_to_f64.c
├── f128_to_i32.c
├── f128_to_i32_r_minMag.c
├── f128_to_i64.c
├── f128_to_i64_r_minMag.c
├── f128_to_ui32.c
├── f128_to_ui32_r_minMag.c
├── f128_to_ui64.c
├── f128_to_ui64_r_minMag.c
├── f16_add.c
├── f16_div.c
├── f16_eq.c
├── f16_eq_signaling.c
├── f16_isSignalingNaN.c
├── f16_le.c
├── f16_le_quiet.c
├── f16_lt.c
├── f16_lt_quiet.c
├── f16_mul.c
├── f16_mulAdd.c
├── f16_rem.c
├── f16_roundToInt.c
├── f16_sqrt.c
├── f16_sub.c
├── f16_to_f128.c
├── f16_to_f32.c
├── f16_to_f64.c
├── f16_to_i32.c
├── f16_to_i32_r_minMag.c
├── f16_to_i64.c
├── f16_to_i64_r_minMag.c
├── f16_to_ui32.c
├── f16_to_ui32_r_minMag.c
├── f16_to_ui64.c
├── f16_to_ui64_r_minMag.c
├── f32_add.c
├── f32_classify.c
├── f32_div.c
├── f32_eq.c
├── f32_eq_signaling.c
├── f32_isSignalingNaN.c
├── f32_le.c
├── f32_le_quiet.c
├── f32_lt.c
├── f32_lt_quiet.c
├── f32_mul.c
├── f32_mulAdd.c
├── f32_rem.c
├── f32_roundToInt.c
├── f32_sqrt.c
├── f32_sub.c
├── f32_to_f128.c
├── f32_to_f16.c
├── f32_to_f64.c
├── f32_to_i32.c
├── f32_to_i32_r_minMag.c
├── f32_to_i64.c
├── f32_to_i64_r_minMag.c
├── f32_to_ui32.c
├── f32_to_ui32_r_minMag.c
├── f32_to_ui64.c
├── f32_to_ui64_r_minMag.c
├── f64_add.c
├── f64_classify.c
├── f64_div.c
├── f64_eq.c
├── f64_eq_signaling.c
├── f64_isSignalingNaN.c
├── f64_le.c
├── f64_le_quiet.c
├── f64_lt.c
├── f64_lt_quiet.c
├── f64_mul.c
├── f64_mulAdd.c
├── f64_rem.c
├── f64_roundToInt.c
├── f64_sqrt.c
├── f64_sub.c
├── f64_to_f128.c
├── f64_to_f16.c
├── f64_to_f32.c
├── f64_to_i32.c
├── f64_to_i32_r_minMag.c
├── f64_to_i64.c
├── f64_to_i64_r_minMag.c
├── f64_to_ui32.c
├── f64_to_ui32_r_minMag.c
├── f64_to_ui64.c
├── f64_to_ui64_r_minMag.c
├── i32_to_f128.c
├── i32_to_f16.c
├── i32_to_f32.c
├── i32_to_f64.c
├── i64_to_f128.c
├── i64_to_f16.c
├── i64_to_f32.c
├── i64_to_f64.c
├── include/
│ └── softfloat/
│ ├── internals.h
│ ├── platform.h
│ ├── primitiveTypes.h
│ ├── primitives.h
│ ├── softfloat.h
│ ├── softfloat.hpp
│ ├── softfloat_types.h
│ └── specialize.h
├── s_add128.c
├── s_add256M.c
├── s_addCarryM.c
├── s_addComplCarryM.c
├── s_addM.c
├── s_addMagsF128.c
├── s_addMagsF16.c
├── s_addMagsF32.c
├── s_addMagsF64.c
├── s_approxRecip32_1.c
├── s_approxRecipSqrt32_1.c
├── s_approxRecipSqrt_1Ks.c
├── s_approxRecip_1Ks.c
├── s_commonNaNToF128UI.c
├── s_commonNaNToF16UI.c
├── s_commonNaNToF32UI.c
├── s_commonNaNToF64UI.c
├── s_compare128M.c
├── s_compare96M.c
├── s_countLeadingZeros16.c
├── s_countLeadingZeros32.c
├── s_countLeadingZeros64.c
├── s_countLeadingZeros8.c
├── s_eq128.c
├── s_f128UIToCommonNaN.c
├── s_f16UIToCommonNaN.c
├── s_f32UIToCommonNaN.c
├── s_f64UIToCommonNaN.c
├── s_le128.c
├── s_lt128.c
├── s_mul128By32.c
├── s_mul128MTo256M.c
├── s_mul128To256M.c
├── s_mul64ByShifted32To128.c
├── s_mul64To128.c
├── s_mul64To128M.c
├── s_mulAddF128.c
├── s_mulAddF16.c
├── s_mulAddF32.c
├── s_mulAddF64.c
├── s_negXM.c
├── s_normRoundPackToF128.c
├── s_normRoundPackToF16.c
├── s_normRoundPackToF32.c
├── s_normRoundPackToF64.c
├── s_normSubnormalF128Sig.c
├── s_normSubnormalF16Sig.c
├── s_normSubnormalF32Sig.c
├── s_normSubnormalF64Sig.c
├── s_propagateNaNF128UI.c
├── s_propagateNaNF16UI.c
├── s_propagateNaNF32UI.c
├── s_propagateNaNF64UI.c
├── s_remStepMBy32.c
├── s_roundMToI64.c
├── s_roundMToUI64.c
├── s_roundPackMToI64.c
├── s_roundPackMToUI64.c
├── s_roundPackToF128.c
├── s_roundPackToF16.c
├── s_roundPackToF32.c
├── s_roundPackToF64.c
├── s_roundPackToI32.c
├── s_roundPackToI64.c
├── s_roundPackToUI32.c
├── s_roundPackToUI64.c
├── s_roundToI32.c
├── s_roundToI64.c
├── s_roundToUI32.c
├── s_roundToUI64.c
├── s_shiftRightJam128.c
├── s_shiftRightJam128Extra.c
├── s_shiftRightJam256M.c
├── s_shiftRightJam32.c
├── s_shiftRightJam64.c
├── s_shiftRightJam64Extra.c
├── s_shortShiftLeft128.c
├── s_shortShiftLeft64To96M.c
├── s_shortShiftRight128.c
├── s_shortShiftRightExtendM.c
├── s_shortShiftRightJam128.c
├── s_shortShiftRightJam128Extra.c
├── s_shortShiftRightJam64.c
├── s_shortShiftRightJam64Extra.c
├── s_shortShiftRightM.c
├── s_sub128.c
├── s_sub1XM.c
├── s_sub256M.c
├── s_subM.c
├── s_subMagsF128.c
├── s_subMagsF16.c
├── s_subMagsF32.c
├── s_subMagsF64.c
├── softfloat_raiseFlags.c
├── softfloat_state.c
├── ui32_to_f128.c
├── ui32_to_f16.c
├── ui32_to_f32.c
├── ui32_to_f64.c
├── ui64_to_f128.c
├── ui64_to_f16.c
├── ui64_to_f32.c
└── ui64_to_f64.c
================================================
FILE CONTENTS
================================================
================================================
FILE: .clang-format
================================================
---
BasedOnStyle: Google
ColumnLimit: '120'
AllowShortCaseLabelsOnASingleLine: 'false'
AllowShortFunctionsOnASingleLine: Empty
AllowShortIfStatementsOnASingleLine: 'false'
IndentWidth: '4'
TabWidth: '4'
UseTab: ForIndentation
...
================================================
FILE: .gitignore
================================================
.cproject
.project
.settings/
main
build/
vp/dependencies/systemc-dist/
*.bin
systemc-*
*.asm
**/nbproject/private/
**/nbproject/Makefile-*.mk
**/nbproject/Package-*.bash
build/
nbbuild/
dist/
nbdist/
.nb-gradle/
nbproject/
sw/basic-gcov/main.*
sw/**/*.o
================================================
FILE: .gitlab-ci.yml
================================================
image: alpine:3.19
variables:
GIT_SUBMODULE_STRATEGY: recursive
cache:
key: $CI_COMMIT_REF_SLUG
paths:
- vp/build
default:
before_script:
- apk update && apk add --no-cache build-base git boost-dev cmake git gdb-multiarch g++-riscv-none-elf gcc-riscv-none-elf newlib-riscv-none-elf valgrind socat
- export RISCV_PREFIX=riscv-none-elf-
build-vp:
stage: build
script:
- sh -c 'env MAKEFLAGS=-j$(nproc) make'
artifacts:
paths:
- vp/build/bin
expire_in: 24h
only:
- master
- merge_requests
test-vp:
stage: test
script:
- cd vp/build
- ctest -V
only:
- master
- merge_requests
================================================
FILE: .gitmodules
================================================
[submodule "vp/src/core/common/gdb-mc/parser/mpc"]
path = vp/src/core/common/gdb-mc/libgdb/mpc
url = https://github.com/orangeduck/mpc
[submodule "tests/integration"]
path = vp/tests
url = https://github.com/agra-uni-bremen/vp-integration-tests.git
[submodule "vp/src/platform/hwitl/virtual-bus"]
path = vp/src/platform/hwitl/virtual-bus
url = https://github.com/agra-uni-bremen/virtual-bus
[submodule "vp/src/platform/hifive/vbb-protocol"]
path = vp/src/platform/hifive/vbb-protocol
url = https://github.com/agra-uni-bremen/virtual-breadboard-protocol.git
[submodule "vp/src/vendor/systemc"]
path = vp/src/vendor/systemc
url = https://github.com/accellera-official/systemc.git
================================================
FILE: CITATION.cff
================================================
# This CITATION.cff file was generated with cffinit.
# Visit https://bit.ly/cffinit to generate yours today!
cff-version: 1.2.0
title: RISC-V VP
message: >-
If you want to cite this software, please use the metadata from this file.
type: software
authors:
- given-names: Vladimir
family-names: Herdt
email: riscv@informatik.uni-bremen.de
affiliation: University of Bremen
orcid: 'https://orcid.org/0000-0002-4481-057X'
- given-names: Group of Computer Architecture
email: riscv@informatik.uni-bremen.de
affiliation: University of Bremen
- given-names: Rolf
family-names: Drechsler
email: drechsler@uni-bremen.de
affiliation: University of Bremen
orcid: 'https://orcid.org/0000-0002-9872-1740'
identifiers:
- type: doi
value: 10.1016/j.sysarc.2020.101756
description: >-
RISC-V based virtual prototype: An extensible and configurable platform for the system-level
repository-code: 'hhttps://github.com/agra-uni-bremen/riscv-vp'
abstract: >-
RISC-V based virtual prototype: An extensible and configurable platform for the system-level
license: MIT
================================================
FILE: Dockerfile
================================================
# XXX: Need Alpine Linux Edge since the latest release (3.19)
# only ships SystemC 2.3.3 and does hence not support aarch64.
FROM alpine:edge
RUN apk update && apk add --no-cache build-base cmake boost-dev \
systemc-dev systemc-static git gcc-riscv-none-elf \
g++-riscv-none-elf newlib-riscv-none-elf gdb-multiarch
RUN adduser -G users -g 'RISC-V VP User' -D riscv-vp
ADD --chown=riscv-vp:users . /home/riscv-vp/riscv-vp
RUN su - riscv-vp -c 'env USE_SYSTEM_SYSTEMC=ON MAKEFLAGS="-j$(nproc)" make -C /home/riscv-vp/riscv-vp'
RUN su - riscv-vp -c 'echo export RISCV_PREFIX=\"riscv-none-elf-\" >> /home/riscv-vp/.profile'
RUN su - riscv-vp -c 'echo export PATH=\"$PATH:/home/riscv-vp/riscv-vp/vp/build/bin\" >> /home/riscv-vp/.profile'
CMD su - riscv-vp
================================================
FILE: LICENSE
================================================
Copyright (c) 2017-2018 Group of Computer Architecture, University of Bremen <riscv@systemc-verification.org>
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.
================================================
FILE: Makefile
================================================
MAKEFLAGS += --no-print-directory
# Whether to use a system-wide SystemC library instead of the vendored one.
USE_SYSTEM_SYSTEMC ?= OFF
vps: vp/src/core/common/gdb-mc/libgdb/mpc/mpc.c vp/build/Makefile
$(MAKE) install -C vp/build
vp/src/core/common/gdb-mc/libgdb/mpc/mpc.c:
git submodule update --init vp/src/core/common/gdb-mc/libgdb/mpc
all: vps vp-display
vp/build/Makefile:
mkdir -p vp/build
cd vp/build && cmake -DUSE_SYSTEM_SYSTEMC=$(USE_SYSTEM_SYSTEMC) ..
vp-eclipse:
mkdir -p vp-eclipse
cd vp-eclipse && cmake ../vp/ -G "Eclipse CDT4 - Unix Makefiles"
env/basic/vp-display/build/Makefile:
mkdir -p env/basic/vp-display/build
cd env/basic/vp-display/build && cmake ..
vp-display: env/basic/vp-display/build/Makefile
$(MAKE) -C env/basic/vp-display/build
vp-clean:
rm -rf vp/build
qt-clean:
rm -rf env/basic/vp-display/build
clean-all: vp-clean qt-clean
clean: vp-clean
codestyle:
find . -type d \( -name .git -o -name dependencies \) -prune -o -name '*.h' -o -name '*.hpp' -o -name '*.cpp' -print | xargs clang-format -i -style=file
================================================
FILE: README.md
================================================
# RISC-V based Virtual Prototype (VP)
<p align="center">
<img src="./img/riscv-vp_logo.png" alt="RISC-V based Virtual Prototype (VP)" width="250"/>
</p>
### Key features of our VP:
- RV32GC and RV64GC core support (i.e. RV32IMAFDC and RV64IMAFDC)
- Implemented in SystemC TLM-2.0
- SW debug capabilities (GDB RSP interface) with Eclipse
- Virtual Breadboard GUI (interactive IO) featuring C++ and Lua modeled digital devices (separate repository)
- FreeRTOS, RIOT, Zephyr, Linux support
- Generic and configurable bus
- CLINT and PLIC-based interrupt controller + additional peripherals
- Instruction-based timing model + annotated TLM 2.0 transaction delays
- Peripherals, e.g. display, flash controller, preliminary ethernet
- Example configuration for the SiFive HiFive1 (currently only Rev. A) board available
- Support for simulation of multi-core platforms
- Machine-, Supervisor- and User-mode (including user traps) privilege levels and CSRs
- Virtual memory support (Sv32, Sv39, Sv48)
For related information, e.g. verification, please visit https://www.informatik.uni-bremen.de/agra/projects/risc-v/ or contact <riscv@informatik.uni-bremen.de>.
We accept pull requests and in general contributions are very welcome.
If you are using the RISC-V VP in a scientific paper, please cite https://doi.org/10.1016/j.sysarc.2020.101756. For the Virtual Breadboard GUI, please refer to https://www.mdpi.com/2079-9268/12/4/52.
In the following we provide build instructions and how to compile and run software on the VP.
#### 1) Build requirements
Mainly the usual build tools and boost is required:
On Ubuntu 20, install these:
```bash
sudo apt-get install autoconf automake autotools-dev curl libmpc-dev libmpfr-dev libgmp-dev gawk build-essential bison flex texinfo libgoogle-perftools-dev libtool patchutils bc zlib1g-dev libexpat-dev libboost-iostreams-dev libboost-program-options-dev libboost-log-dev qt5-default
```
On Fedora, following actions are required:
```bash
sudo dnf install autoconf automake curl libmpc-devel mpfr-devel gmp-devel gawk bison flex texinfo gperf libtool patchutils bc zlib-devel expat-devel cmake boost-devel qt5-qtbase qt5-qtbase-devel
sudo dnf groupinstall "C Development Tools and Libraries"
#optional debuginfo
sudo dnf debuginfo-install boost-iostreams boost-program-options boost-regex bzip2-libs glibc libgcc libicu libstdc++ zlib
```
#### 2) Build this RISC-V Virtual Prototype:
Check out all submodules (`git submodule update --init --recursive`), and type `make all`. This script does the following for you:
>
>i) in *vp/dependencies* folder (will download and compile SystemC, and build a local version of the softfloat library):
>
>```bash
>./build_systemc_233.sh
>./build_softfloat.sh
>```
>
>
>ii) in *vp* folder (requires the *boost* C++ library):
>
>```bash
>mkdir build
>cd build
>cmake ..
>make install
>```
#### 3) Building the interactive environment GUI (`vp-breadboard`)
The GUI for interacting with the VP has moved to [https://github.com/agra-uni-bremen/virtual-breadboard](https://github.com/agra-uni-bremen/virtual-breadboard).
#### 3) Building SW examples using the GNU toolchain
##### Requirements
In order to test the software examples, a configured RISC-V GNU toolchain is required in your `$PATH`.
Several standard packages are required to build the toolchain.
For more information on prerequisites for the RISC-V GNU toolchain visit https://github.com/riscv/riscv-gnu-toolchain.
With the packages installed, the toolchain can be build as follows:
```bash
# in some source folder
git clone https://github.com/riscv/riscv-gnu-toolchain.git
cd riscv-gnu-toolchain
git submodule update --init --recursive # this may take a while
./configure --prefix=$(pwd)/../riscv-gnu-toolchain-dist-rv32imac-ilp32 --with-arch=rv32imac --with-abi=ilp32
make -j$(nproc)
```
If wanted, move the `riscv-gnu-toolchain-dist-rv32imac-ilp32` folder to your `/opt/` folder and add it to your path in your `~/.bashrc`
(e.g. `PATH=$PATH:/opt/riscv-gnu-toolchain-dist-rv32imac-ilp32/bin`)
##### Running the examples
In *sw*:
```bash
cd simple-sensor # can be replaced with different example
make # (requires RISC-V GNU toolchain in PATH)
make sim # (requires *riscv-vp*, i.e. *vp/build/bin/riscv-vp*, executable in PATH)
```
Please note, if *make* is called without the *install* argument in step 2, then the *riscv-vp* executable is available in *vp/build/src/platform/basic/riscv-vp*.
This will also copy the VP binaries into the *vp/build/bin* folder.
#### Alternative Setup: Docker
Instead of compiling the riscv-vp manually, a `Dockerfile` is also
provided which eases this process. In order to build a Docker image from
this file run the following command:
$ docker build -t riscv-vp .
Afterwards, start a new Docker container using:
$ docker run --rm -it riscv-vp
Within this Docker container, the riscv-vp source tree is available in
`/home/riscv-vp/riscv-vp/`. A RISC-V cross compiler toolchain is also
part of the container. As such, it is possible to compile and run any of
the examples from the `./sw` subdirectory in this container. For
example:
$ cd /home/riscv-vp/riscv-vp/sw/basic-c/
$ make
$ make sim
#### FAQ
**Q:** How do I exit the VP?
**A:** All VPs use the input TTY in raw mode and forward all control
characters to the guest. For this reason, one cannot use Ctrl-c to exit
the VP. Instead, press Ctrl-a to enter command mode and press Ctrl-x to
exit the VP.
**Q:** How do I emit a Ctrl-a control character?
**A:** Enter control mode using Ctrl-a and press Ctrl-a again to send a
literal Ctrl-a control character to the guest.
#### Acknowledgements:
This work was supported in part by the German Federal Ministry of Education and Research (BMBF) within the project CONFIRM under contract no. 16ES0565 and within the project SATiSFy under contract no. 16KIS0821K and within the project VerSys under contract no. 01IW19001 and within the project Scale4Edge under contract no. 16ME0127, and by the University of Bremen’s graduate school SyDe, funded by the German Excellence Initiative.
================================================
FILE: env/basic/vp-display/CMakeLists.txt
================================================
cmake_minimum_required(VERSION 3.1.0)
project(vp-display) # Your project name
set(CMAKE_CXX_STANDARD 11) # This is equal to QMAKE_CXX_FLAGS += -std=c++0x
# Find includes in corresponding build directories
set(CMAKE_INCLUDE_CURRENT_DIR ON)
set(CMAKE_AUTOMOC ON)
set(CMAKE_AUTOUIC ON)
find_package(Qt5Widgets CONFIG REQUIRED)
set(SOURCES
main.cpp
mainwindow.cpp
vpdisplayserver.cpp
)
set(HEADERS
mainwindow.h
vpdisplayserver.h
framebuffer.h
)
set(UI mainwindow.ui)
add_executable(vp-display ${SOURCES} ${HEADERS} ${UI})
target_link_libraries(vp-display Qt5::Widgets pthread)
================================================
FILE: env/basic/vp-display/VP-Display.pro
================================================
#-------------------------------------------------
#
# Project created by QtCreator 2018-09-10T15:30:06
#
#-------------------------------------------------
QT += core gui
greaterThan(QT_MAJOR_VERSION, 4): QT += widgets
TARGET = VP-Display
TEMPLATE = app
CONFIG += c++11
# The following define makes your compiler emit warnings if you use
# any feature of Qt which has been marked as deprecated (the exact warnings
# depend on your compiler). Please consult the documentation of the
# deprecated API in order to know how to port your code away from it.
DEFINES += QT_DEPRECATED_WARNINGS
# You can also make your code fail to compile if you use deprecated APIs.
# In order to do so, uncomment the following line.
# You can also select to disable deprecated APIs only up to a certain version of Qt.
#DEFINES += QT_DISABLE_DEPRECATED_BEFORE=0x060000 # disables all the APIs deprecated before Qt 6.0.0
SOURCES += \
main.cpp \
mainwindow.cpp \
vpdisplayserver.cpp
HEADERS += \
mainwindow.h \
vpdisplayserver.h \
framebuffer.h
FORMS += \
mainwindow.ui
================================================
FILE: env/basic/vp-display/framebuffer.h
================================================
#pragma once
#include <inttypes.h>
#include <cassert>
#include <cstring>
#define SHMKEY 1338
struct Framebuffer {
static constexpr uint16_t screenWidth = 800;
static constexpr uint16_t screenHeight = 600;
typedef uint16_t Color;
struct Point {
uint32_t x;
uint32_t y;
inline Point() : x(0), y(0){};
inline Point(uint32_t x, uint32_t y) : x(x), y(y){};
};
struct PointF {
float x;
float y;
inline PointF() : x(0), y(0){};
inline PointF(float x, float y) : x(x), y(y){};
inline PointF(Point p) : x(p.x), y(p.y){};
};
struct Frame {
Color raw[screenHeight][screenWidth]; // Notice: Screen is on side
};
enum class Type : uint8_t { foreground, background };
uint8_t activeFrame;
enum class Command : uint8_t {
none = 0,
clearAll,
fillFrame,
applyFrame,
drawLine,
} volatile command;
union Parameter {
struct {
//fillframe
Type frame;
Color color;
} fill;
struct {
//drawLine
Type frame;
PointF from;
PointF to;
Color color;
} line;
inline Parameter(){};
} parameter;
Frame frames[2];
Frame background;
Framebuffer() : activeFrame(0), command(Command::none){};
Frame& getActiveFrame() {
return frames[activeFrame % 2];
}
Frame& getInactiveFrame() {
return frames[(activeFrame + 1) % 2];
}
Frame& getBackground() {
return background;
}
Frame& getFrame(Type type) {
if (type == Type::foreground)
return getInactiveFrame();
else if (type == Type::background)
return getBackground();
assert(false && "Get invalid frame type");
return background;
}
};
inline Framebuffer::PointF operator+(const Framebuffer::PointF l, Framebuffer::PointF const r) {
return Framebuffer::PointF(l.x + r.x, l.y + r.y);
}
================================================
FILE: env/basic/vp-display/main.cpp
================================================
#include <QApplication>
#include "mainwindow.h"
int main(int argc, char *argv[]) {
QApplication a(argc, argv);
VPDisplay w;
w.show();
return a.exec();
}
================================================
FILE: env/basic/vp-display/mainwindow.cpp
================================================
#include "mainwindow.h"
#include <qpainter.h>
#include <cassert>
#include "framebuffer.h"
#include "ui_mainwindow.h"
VPDisplay::VPDisplay(QWidget* mparent) : QWidget(mparent) {
framebuffer = server.createSM();
frame = new QImage(Framebuffer::screenWidth, Framebuffer::screenHeight,
QImage::Format_RGB444); // two bytes per pixel
resize(Framebuffer::screenWidth, Framebuffer::screenHeight);
setFixedSize(size());
server.startListening(std::bind(&VPDisplay::notifyChange, this, std::placeholders::_1));
}
VPDisplay::~VPDisplay() {
delete frame;
}
void VPDisplay::drawMainPage(QImage* mem) {
Framebuffer::Frame activeFrame = framebuffer->getActiveFrame();
Framebuffer::Frame background = framebuffer->getBackground();
for (int row = 0; row < mem->height(); row++) {
uint16_t* line = reinterpret_cast<uint16_t*>(mem->scanLine(row)); // Two bytes per pixel
for (int x = 0; x < mem->width(); x++) {
line[x] = activeFrame.raw[row][x] == 0 ? background.raw[row][x] : activeFrame.raw[row][x];
}
}
}
void VPDisplay::paintEvent(QPaintEvent*) {
QPainter painter(this);
// painter.scale(size_factor, size_factor);
// Draw Header
// QPainter mempaint(&memory);
drawMainPage(frame);
painter.drawImage(QPoint(0, 0), *frame);
painter.end();
}
void VPDisplay::notifyChange(bool success) {
assert(success);
update();
}
================================================
FILE: env/basic/vp-display/mainwindow.h
================================================
#pragma once
#include <QMainWindow>
#include <cassert>
#include "vpdisplayserver.h"
namespace Ui {
class VPDisplay;
}
class VPDisplay : public QWidget {
Q_OBJECT
Framebuffer* framebuffer;
QImage* frame;
VPDisplayserver server;
public:
VPDisplay(QWidget* mparent = 0);
~VPDisplay();
void paintEvent(QPaintEvent*);
// void keyPressEvent(QKeyEvent *e);
void drawMainPage(QImage* mem);
void notifyChange(bool success);
};
================================================
FILE: env/basic/vp-display/mainwindow.ui
================================================
<ui version="4.0">
<class>MainWindow</class>
<widget class="QMainWindow" name="MainWindow" >
<property name="geometry" >
<rect>
<x>0</x>
<y>0</y>
<width>400</width>
<height>300</height>
</rect>
</property>
<property name="windowTitle" >
<string>MainWindow</string>
</property>
<widget class="QMenuBar" name="menuBar" />
<widget class="QToolBar" name="mainToolBar" />
<widget class="QWidget" name="centralWidget" />
<widget class="QStatusBar" name="statusBar" />
</widget>
<layoutDefault spacing="6" margin="11" />
<pixmapfunction></pixmapfunction>
<resources/>
<connections/>
</ui>
================================================
FILE: env/basic/vp-display/vpdisplayserver.cpp
================================================
#include "vpdisplayserver.h"
#include <stdio.h>
#include <stdlib.h>
#include <sys/ipc.h>
#include <sys/shm.h>
#include <sys/types.h>
#include <iostream>
VPDisplayserver::VPDisplayserver(unsigned int sharedMemoryKey) : mSharedMemoryKey(sharedMemoryKey), stop(false) {}
VPDisplayserver::~VPDisplayserver() {
stop.store(true);
active_watch.join();
}
Framebuffer* VPDisplayserver::createSM() {
int shmid;
// TODO: Dont create, but check if exists
if ((shmid = shmget(mSharedMemoryKey, sizeof(Framebuffer), 0666)) < 0) {
perror("shmget");
exit(1);
}
std::cout << "SHMID: " << shmid << std::endl;
framebuffer = reinterpret_cast<Framebuffer*>(shmat(shmid, nullptr, 0));
if (framebuffer == (Framebuffer*)-1) {
perror("shmat");
exit(1);
}
return framebuffer;
}
void VPDisplayserver::startListening(std::function<void(bool)> notifyChange) {
// TODO: While loop around buffer changer
active_watch = std::thread([=]() {
uint8_t lastFrame = -1;
while (!stop.load()) {
if (framebuffer->activeFrame != lastFrame) {
notifyChange(true);
lastFrame = framebuffer->activeFrame;
}
// std::this_thread::sleep_for(std::chrono::milliseconds(100));
}
});
notifyChange(true);
}
================================================
FILE: env/basic/vp-display/vpdisplayserver.h
================================================
#pragma once
#include <atomic>
#include <functional>
#include <thread>
#include "framebuffer.h"
class VPDisplayserver {
unsigned int mSharedMemoryKey;
Framebuffer* framebuffer;
std::atomic<bool> stop;
std::thread active_watch;
public:
VPDisplayserver(unsigned int sharedMemoryKey = 1338);
~VPDisplayserver();
Framebuffer* createSM();
void startListening(std::function<void(bool)> notifyChange);
};
================================================
FILE: sw/.gitignore
================================================
main
================================================
FILE: sw/Makefile
================================================
all:
find . -maxdepth 1 -type d \( ! -name . \) -exec bash -c "cd '{}' && make" \;
clean:
find . -maxdepth 1 -type d \( ! -name . \) -exec bash -c "cd '{}' && make clean" \;
================================================
FILE: sw/Makefile.common
================================================
RISCV_PREFIX ?= riscv32-unknown-elf-
override CC = $(RISCV_PREFIX)gcc
override CXX = $(RISCV_PREFIX)g++
override LD = $(RISCV_PREFIX)gcc
ASFLAGS ?= $(CFLAGS)
SIM_TARGET ?= sim-default
# ISA Version 2.2 is the last version where zicsr is still
# supported as part of the base ISA. Use that for now until
# _zicsr is widely supported by existing cross-compilers.
SUPPORTS_MISA ?= $(shell echo "typedef int dont_be_pedantic;" | $(RISCV_PREFIX)gcc -march=rv32imac -mabi=ilp32 -misa-spec=2.2 -E - > /dev/null 2>&1 && echo 1 || echo 0)
ifeq (1,$(SUPPORTS_MISA))
CFLAGS += -misa-spec=2.2
CXXFLAGS += -misa-spec=2.2
endif
VP ?= riscv-vp
VP_FLAGS ?= --intercept-syscalls --error-on-zero-traphandler=true
EXECUTABLE ?= main
OBJECTS ?= main.o
########################################################################
$(EXECUTABLE): $(OBJECTS)
$(LD) $(CXXFLAGS) $(CFLAGS) -o $@ $(LDFLAGS) $^ $(LDLIBS)
%.o: %.S
$(CC) $(CPPFLAGS) $(ASFLAGS) -c $<
%.o: %.c
$(CC) $(CPPFLAGS) $(CFLAGS) -c $<
%.o: %.cpp
$(CXX) $(CPPFLAGS) $(CXXFLAGS) -c $<
########################################################################
sim: $(SIM_TARGET)
sim-default: $(EXECUTABLE)
$(VP) $(VP_FLAGS) $<
dump-elf: $(EXECUTABLE)
$(RISCV_PREFIX)readelf -a main
dump-code: $(EXECUTABLE)
$(RISCV_PREFIX)objdump -D main
clean:
rm -f $(OBJECTS) $(EXECUTABLE) $(CLEAN_EXTRA)
.PHONY: sim sim-default dump-elf dump-code clean
.DEFAULT_GOAL := $(EXECUTABLE)
================================================
FILE: sw/README.md
================================================
These SW examples demonstrate basic bare-metal applications and applications that use the C-library. In particular, the applications using the C-library require support for system calls (syscalls). Syscalls are handled in one of two ways in the VP:
1) By default the VP will trigger a trap and thus jump to the trap/interrupt handler. The handler will detect that the reason is a syscall and re-direct the syscall to the syscall handler (or some other peripheral) through memory mapped I/O. This requires to provide and setup a trap handler. This can be done by providing a custom entry-point that performs the required setup and then jumps to the crt0.S entry code of the C-library (which in turn will call the main function). The *printf* SW example demonstrates this case.
2) With the "--intercept-syscalls" command line argument, the VP will directly intercept and handle syscalls, hence it is not necessary to setup a trap handler. Thus, no designated startup code (i.e. bootstrap.S) is required to run applications that use the C-library. For example see the *c++-lib* SW example.
The provided SW examples demonstrate both approaches for dealing with syscalls.
The VP also supports the FreeRTOS (see https://github.com/agra-uni-bremen/riscv-freertos) and Zephyr (see https://www.zephyrproject.org/ - use the Zephyr *hifive* board option when building Zephyr applications and use the *hifive-vp* configuration for executing them) operating systems.
================================================
FILE: sw/basic-asm/Makefile
================================================
OBJECTS = sum.o
CFLAGS = -march=rv32i -mabi=ilp32
LDFLAGS = -nostartfiles -Wl,--no-relax
VP_FLAGS = --error-on-zero-traphandler=true
include ../Makefile.common
================================================
FILE: sw/basic-asm/sum.S
================================================
.globl _start
.equ SYSCALL_ADDR, 0x02010000
.macro SYS_EXIT, exit_code
li a7, 93
li a0, \exit_code
li t0, SYSCALL_ADDR
csrr a6, mhartid
sw a6, 0(t0)
.endm
# program entry-point
_start:
li a0,50
li a1,100
li a2,0
loop:
bgt a0,a1,end
add a2,a2,a0
addi a0,a0,1
j loop
end:
# call exit (SYS_EXIT=93) with exit code 0 (argument in a0)
SYS_EXIT 0
================================================
FILE: sw/basic-c/Makefile
================================================
OBJECTS = main.o sum.o bootstrap.o
CFLAGS = -march=rv32i -mabi=ilp32
LDFLAGS = -nostartfiles -Wl,--no-relax
include ../Makefile.common
================================================
FILE: sw/basic-c/bootstrap.S
================================================
.globl _start
.globl main
_start:
jal main
# call exit (SYS_EXIT=93) with exit code 0 (argument in a0)
li a7,93
li a0,0
ecall
================================================
FILE: sw/basic-c/main.c
================================================
int sum(int end);
int x = 5;
int y;
int main() {
int a = 6;
int b = 7;
a = a + b + x + y;
a = sum(a);
return a;
}
================================================
FILE: sw/basic-c/sum.c
================================================
int sum(int end) {
int ans = end;
for (int i=1; i<end; ++i) {
ans += i;
}
return ans;
}
================================================
FILE: sw/basic-debug/Makefile
================================================
OBJECTS = main.o bootstrap.o
CFLAGS = -g3 -march=rv32im -mabi=ilp32
LDFLAGS = -nostartfiles -Wl,--no-relax
VP_FLAGS = --intercept-syscalls --error-on-zero-traphandler=true --debug-mode
include ../Makefile.common
================================================
FILE: sw/basic-debug/bootstrap.S
================================================
.align 6
.globl _start
.globl main
_start:
jal main
# call exit (SYS_EXIT=93) with exit code 0 (argument in a0)
li a7,93
li a0,0
ecall
================================================
FILE: sw/basic-debug/eclipse-remote-debug-readme.txt
================================================
Start Eclipse
File -> New -> Makefile Project with Existing Code
Select the software folder containing the Makefile
Run -> Debug Configurations ...
C/C++ Remote Application (List Entry on the left side): Click "New" Button
Main Tab
- C/C++ Application Name: Enter name, typically "main"
- Using GDB (DSF) Automatic Remote Launcher: Click "Select other"
-> Use configuration specific settings
-> GDB (DSF) Manual Remote Debug Launcher
Debugger Tab
- GDB debugger: riscv32-unknown-elf-gdb [Sub-tab Main]
- Connection: Port Number 5005 [Sub-tab Connection]
Click "Debug" Button (lower right corner) to start debugging
-> Launch the VP in debug mode first: riscv-vp --debug-mode main
-> Perhaps it is necessary to refresh the Eclipse project view in case the executable (typically main) cannot be found (the "Debug" button is greyed out in this case)
================================================
FILE: sw/basic-debug/main.c
================================================
int x = 5;
int y;
int f(int a, int b) {
if (a > 0) {
int ans = a + b;
return ans;
}
a = -a;
return b + a;
}
int main() {
int a = 5;
int b = 3;
b--;
a = a / b;
a = a * 2;
a = f(x, y);
return a;
}
================================================
FILE: sw/basic-debug/remote-debug-readme.txt
================================================
In the first terminal run our VP in debug mode (wraps the core iss in a debug stub):
riscv-vp --debug-mode --intercept-syscalls main
In the other terminal run:
riscv32-unknown-elf-gdb
Inside of gdb then (for example):
file main
target remote :5005
b main.c:14
continue
p x
p y
step
continue
This will load the symbols from the *main* elf file (note: this one should match the one loaded in our VP). The *target remote* command is passed host and port number. In this case localhost is used.
Note: you can use 'set debug remote 1' in gdb to observe the packets send and received by gdb (might be useful for debugging).
================================================
FILE: sw/basic-debug/test-ignore
================================================
================================================
FILE: sw/basic-dma/Makefile
================================================
OBJECTS = main.o irq.o bootstrap.o
CFLAGS = -march=rv32imac -mabi=ilp32
LDFLAGS = -nostartfiles -Wl,--no-relax
include ../Makefile.common
================================================
FILE: sw/basic-dma/bootstrap.S
================================================
.globl _start
.globl init
.globl main
.globl level_1_interrupt_handler
.equ PLIC_ENABLED_IRQ_ADDR, 0x40002000
_start:
jal init
la t0, level_0_interrupt_handler
csrw mtvec, t0
li t1, 0x888
csrw mie, t1
csrwi mstatus, 8
li t0, PLIC_ENABLED_IRQ_ADDR
li t1, -1
sw t1, 0(t0)
sw t1, 4(t0)
jal main
# call exit (SYS_EXIT=93) with exit code 0 (argument in a0)
li a7,93
li a0,0
ecall
/*
* Interrupt handler for non-nested interrupts. Only selected registers are stored/re-stored, i.e. those not preserved on function calls.
*/
#define STORE sw
#define LOAD lw
#define REGBYTES 4
.align 4
level_0_interrupt_handler:
// store execution context on the stack (register content)
addi sp, sp, -REGBYTES * 32
STORE x1, 0x0(sp)
STORE x4, 3 * REGBYTES(sp)
STORE x5, 4 * REGBYTES(sp)
STORE x6, 5 * REGBYTES(sp)
STORE x7, 6 * REGBYTES(sp)
STORE x10, 9 * REGBYTES(sp)
STORE x11, 10 * REGBYTES(sp)
STORE x12, 11 * REGBYTES(sp)
STORE x13, 12 * REGBYTES(sp)
STORE x14, 13 * REGBYTES(sp)
STORE x15, 14 * REGBYTES(sp)
STORE x16, 15 * REGBYTES(sp)
STORE x17, 16 * REGBYTES(sp)
STORE x28, 27 * REGBYTES(sp)
STORE x29, 28 * REGBYTES(sp)
STORE x30, 29 * REGBYTES(sp)
STORE x31, 30 * REGBYTES(sp)
// load interrupt/trap reason and call external C function to handle it
csrr a0, mcause
jal level_1_interrupt_handler
// re-store the saved context
LOAD x1, 0x0(sp)
LOAD x4, 3 * REGBYTES(sp)
LOAD x5, 4 * REGBYTES(sp)
LOAD x6, 5 * REGBYTES(sp)
LOAD x7, 6 * REGBYTES(sp)
LOAD x10, 9 * REGBYTES(sp)
LOAD x11, 10 * REGBYTES(sp)
LOAD x12, 11 * REGBYTES(sp)
LOAD x13, 12 * REGBYTES(sp)
LOAD x14, 13 * REGBYTES(sp)
LOAD x15, 14 * REGBYTES(sp)
LOAD x16, 15 * REGBYTES(sp)
LOAD x17, 16 * REGBYTES(sp)
LOAD x28, 27 * REGBYTES(sp)
LOAD x29, 28 * REGBYTES(sp)
LOAD x30, 29 * REGBYTES(sp)
LOAD x31, 30 * REGBYTES(sp)
addi sp, sp, REGBYTES * 32
mret
================================================
FILE: sw/basic-dma/irq.c
================================================
#include "irq.h"
#include "assert.h"
#define RISCV_MACHINE_SOFTWARE_INTERRUPT 3
#define RISCV_MACHINE_TIMER_INTERRUPT 7
#define RISCV_MACHINE_EXTERNAL_INTERRUPT 11
#define PLIC_BASE 0x40000000
#define IRQ_TABLE_NUM_ENTRIES 64
static volatile uint32_t * const PLIC_INTERRUPT_ENABLE_START = (uint32_t * const)(PLIC_BASE + 0x2000);
static volatile uint32_t * const PLIC_CLAIM_AND_RESPONSE_REGISTER = (uint32_t * const)(PLIC_BASE + 0x200004);
static void irq_empty_handler() {}
static irq_handler_t irq_handler_table[IRQ_TABLE_NUM_ENTRIES] = { [ 0 ... IRQ_TABLE_NUM_ENTRIES-1 ] = irq_empty_handler };
#define CLINT_BASE 0x2000000
volatile uint64_t* mtime = (uint64_t*)(CLINT_BASE + 0xbff8);
volatile uint64_t* mtimecmp = (uint64_t*)(CLINT_BASE + 0x4000);
static irq_handler_t timer_irq_handler = 0;
void level_1_interrupt_handler(uint32_t cause) {
switch (cause & 0xf) {
case RISCV_MACHINE_EXTERNAL_INTERRUPT: {
asm volatile ("csrc mip, %0" : : "r" (0x800));
uint32_t irq_id = *PLIC_CLAIM_AND_RESPONSE_REGISTER;
irq_handler_table[irq_id]();
*PLIC_CLAIM_AND_RESPONSE_REGISTER = 1;
return;
}
case RISCV_MACHINE_TIMER_INTERRUPT: {
// Note: the pending timer interrupt bit will be automatically cleared when writing to the *mtimecmp* register of this hart
if (timer_irq_handler) {
// let the user registered handler clear the timer interrupt bit
timer_irq_handler();
} else {
// reset the *mtimecmp* register to zero to clear the pending bit
*mtimecmp = 0;
}
return;
}
}
assert (0 && "unsupported cause");
}
void register_interrupt_handler(uint32_t irq_id, irq_handler_t fn) {
assert (irq_id < IRQ_TABLE_NUM_ENTRIES);
// enable interrupt
volatile uint32_t* const reg = (PLIC_INTERRUPT_ENABLE_START + irq_id/32);
*reg |= 1 << (irq_id%32);
// set a prio different to zero (which means do-not-interrupt)
*((uint32_t*) (PLIC_BASE + irq_id*sizeof(uint32_t))) = 1;
irq_handler_table[irq_id] = fn;
}
void register_timer_interrupt_handler(irq_handler_t fn) {
timer_irq_handler = fn;
}
================================================
FILE: sw/basic-dma/irq.h
================================================
#ifndef __RISCV_IRQ_H__
#define __RISCV_IRQ_H__
#include "stdint.h"
typedef void (*irq_handler_t)(void);
void register_interrupt_handler(uint32_t irq_id, irq_handler_t fn);
void register_timer_interrupt_handler(irq_handler_t fn);
extern volatile uint64_t* mtime;
extern volatile uint64_t* mtimecmp;
#endif
================================================
FILE: sw/basic-dma/main.c
================================================
#include "stdint.h"
#include "irq.h"
static volatile char * const TERMINAL_ADDR = (char * const)0x20000000;
static volatile uint32_t * const DMA_SRC_ADDR = (uint32_t * const)0x70000000;
static volatile uint32_t * const DMA_DST_ADDR = (uint32_t * const)0x70000004;
static volatile uint32_t * const DMA_LEN_ADDR = (uint32_t * const)0x70000008;
static volatile uint32_t * const DMA_OP_ADDR = (uint32_t * const)0x7000000C;
static volatile uint32_t * const DMA_STAT_ADDR = (uint32_t * const)0x70000010;
static const uint32_t DMA_OP_NOP = 0;
static const uint32_t DMA_OP_MEMCPY = 1;
volatile _Bool dma_completed = 0;
void dma_irq_handler() {
dma_completed = 1;
}
void init() {
register_interrupt_handler(4, dma_irq_handler);
}
int main() {
uint8_t src[32] = { [ 0 ... 31 ] = 70 };
uint8_t dst[32] = { 0 };
dma_completed = 0;
*DMA_SRC_ADDR = (uint32_t)(&src[0]);
*DMA_DST_ADDR = (uint32_t)(&dst[0]);
*DMA_LEN_ADDR = sizeof(src);
*DMA_OP_ADDR = DMA_OP_MEMCPY;
while (!dma_completed) {
asm volatile ("wfi");
}
for (int i=0; i<32; ++i) {
*TERMINAL_ADDR = dst[i];
}
*TERMINAL_ADDR = '\n';
return 0;
}
================================================
FILE: sw/basic-e/Makefile
================================================
OBJECTS = sum.o
CFLAGS = -march=rv32e -mabi=ilp32e
LDFLAGS = -nostartfiles -Wl,--no-relax
VP_FLAGS = --use-E-base-isa --error-on-zero-traphandler=true
include ../Makefile.common
================================================
FILE: sw/basic-e/sum.S
================================================
.globl _start
.equ SYSCALL_ADDR, 0x02010000
.macro SYS_EXIT, exit_code
li a5, 93
li a0, \exit_code
li t0, SYSCALL_ADDR
csrr t1, mhartid
sw t1, 0(t0)
.endm
# program entry-point
_start:
li a0,50
li a1,100
li a2,0
loop:
bgt a0,a1,end
add a2,a2,a0
addi a0,a0,1
j loop
end:
# call exit (SYS_EXIT=93) with exit code 0 (argument in a0)
SYS_EXIT 0
================================================
FILE: sw/basic-gcov/Makefile
================================================
OBJECTS = main.o
CFLAGS = --coverage -march=rv32ima -mabi=ilp32
LDFLAGS = --coverage
VP_FLAGS = --error-on-zero-traphandler=true
CLEAN_EXTRA = main.c.gcov main.gcda main.gcno cov*.html
main.gcda: main
riscv-vp --intercept-syscalls --error-on-zero-traphandler=true main
# use -b option to display branch coverage too
dump-coverage: main.gcda
$(RISCV_PREFIX)gcov main.c
dump-html-coverage: main.gcda
gcovr --gcov-executable $(RISCV_PREFIX)gcov -b -r . --html-details -o cov.html
include ../Makefile.common
.DEFAULT_GOAL := main.gcda
================================================
FILE: sw/basic-gcov/test-ignore
================================================
================================================
FILE: sw/basic-gpio/Makefile
================================================
OBJECTS = bootstrap.o main.o uart.o
CFLAGS = -g3 -march=rv32i -mabi=ilp32
LDLIBS = -Tlink.ld -nostartfiles -Wl,--no-relax
VP = microrv32-vp
VP_FLAGS =
hex: $(EXECUTABLE)
../elf2bin.py ./main gpio.hex 0x4020
include ../Makefile.common
================================================
FILE: sw/basic-gpio/bootstrap.S
================================================
.globl _start
.globl main
.equ SYSCALL_ADDR, 0x02010000
.macro INIT_HW_PLATFORM
and x1,x0,x0
and x2,x0,x0
and x3,x0,x0
and x4,x0,x0
and x5,x0,x0
and x6,x0,x0
and x7,x0,x0
and x8,x0,x0
and x9,x0,x0
and x10,x0,x0
and x11,x0,x0
and x12,x0,x0
and x13,x0,x0
and x14,x0,x0
and x15,x0,x0
and x16,x0,x0
and x17,x0,x0
and x18,x0,x0
and x19,x0,x0
and x20,x0,x0
and x21,x0,x0
and x22,x0,x0
and x23,x0,x0
and x24,x0,x0
and x25,x0,x0
and x26,x0,x0
and x27,x0,x0
and x28,x0,x0
and x29,x0,x0
and x30,x0,x0
and x31,x0,x0
.endm
.macro SYS_EXIT, exit_code
li a7, 93
li a0, \exit_code
li t0, SYSCALL_ADDR
csrr a6, mhartid
sw a6, 0(t0)
.endm
# .macro SYS_EXIT, exit_code
# li a7, 93
# li a0, \exit_code
# li t0, SYSCALL_ADDR
# sw a7, 0(t0)
# .endm
_start:
# initialize hw-platform
INIT_HW_PLATFORM
la sp, stack_end
jal main
# call exit (SYS_EXIT=93) with exit code 0 (argument in a0)
SYS_EXIT 0
.align 4
stack_begin:
.zero 1024
stack_end:
================================================
FILE: sw/basic-gpio/gpio.h
================================================
#ifndef GPIO_H
#define GPIO_H
#endif /* GPIO_H */
================================================
FILE: sw/basic-gpio/link.ld
================================================
OUTPUT_ARCH( "riscv" )
ENTRY(_start)
SECTIONS
{
. = 0x80000000;
.text.init : { *(.text.init) }
. = ALIGN(0x1000);
.tohost : { *(.tohost) }
. = ALIGN(0x1000);
.text : { *(.text) }
. = ALIGN(0x1000);
.data : { *(.data) }
.bss : { *(.bss) }
_end = .;
}
================================================
FILE: sw/basic-gpio/main.c
================================================
#include <stdint.h>
#include <stdio.h>
#include "platform.h"
#include "uart.h"
#include "util.h"
//#include "gpio.h"
void wait(uint32_t nOps) {
/*
* TODO correlate nOps to clocks/time waited
*/
for(uint32_t i = 0; i < nOps; i++) {
asm("nop");
}
}
int main(int argc, char **argv) {
uint8_t val = 1;
*GPIO_BANK_A_DIRECTION_ADDR = 0x000000ff; // set all pins to output
*GPIO_BANK_A_OUTPUT_ADDR = 0x01; // output 0x01 to all 8 pins of gpio bank A
wait(10);
*LED_ADDR = 0x05;
wait(10);
*LED_ADDR = 0x0A;
wait(10);
// bit shift pattern until only 0x55 and 0xAA are present
for(uint8_t i=0; i<10; i++) {
*GPIO_BANK_A_OUTPUT_ADDR = val;
wait(10);
val = (val << 1) | (i & 1);
}
*LED_ADDR = 0x0A;
return 0;
}
================================================
FILE: sw/basic-gpio/platform.h
================================================
#ifndef PLATFORM_H
#define PLATFORM_H
//#define MICRORV
#ifdef MICRORV
// LED
static volatile uint32_t *LED_ADDR = (uint32_t *)0x81000000;
// UART
static volatile uint32_t *UART_TX_DATA_ADDR = (uint32_t *)0x82000000;
static volatile uint32_t *UART_TX_CTRL_ADDR = (uint32_t *)0x82000004;
static volatile uint32_t *UART_RX_DATA_ADDR = (uint32_t *)0x82000008;
// CLIC
static volatile uint64_t *MTIMECMP_REG = (uint64_t *)0x02004000;
static volatile uint64_t *MTIME_REG = (uint64_t *)0x0200bff8;
// GPIO
static volatile uint32_t *GPIO_BANK_A_DIRECTION_ADDR = (uint32_t *)0x83000000;
static volatile uint32_t *GPIO_BANK_A_OUTPUT_ADDR = (uint32_t *)0x83000004;
static volatile uint32_t *GPIO_BANK_A_INPUT_ADDR = (uint32_t *)0x83000008;
#else
// LED
static volatile uint32_t *LED_ADDR = (uint32_t *)0x81000000;
// UART
static volatile uint32_t *UART_TX_DATA_ADDR = (uint32_t *)0x82000000;
static volatile uint32_t *UART_TX_CTRL_ADDR = (uint32_t *)0x82000004;
static volatile uint32_t *UART_RX_DATA_ADDR = (uint32_t *)0x82000008;
// CLIC
static volatile uint64_t *MTIMECMP_REG = (uint64_t *)0x02004000;
static volatile uint64_t *MTIME_REG = (uint64_t *)0x0200bff8;
// GPIO
static volatile uint32_t *GPIO_BANK_A_DIRECTION_ADDR = (uint32_t *)0x83000000;
static volatile uint32_t *GPIO_BANK_A_OUTPUT_ADDR = (uint32_t *)0x83000004;
static volatile uint32_t *GPIO_BANK_A_INPUT_ADDR = (uint32_t *)0x83000008;
#endif
#endif /* PLATFORM_H */
================================================
FILE: sw/basic-gpio/uart.c
================================================
#include "uart.h"
#include "platform.h"
#include <stdint.h>
int sendString(char* str, long len) {
long cnt = len;
const char *s = (const char *)str;
while (cnt > 0) {
--cnt;
putChr(*s);
s++;
}
return len;
}
void putChr(char chr) {
#ifdef MICRORV
uint32_t tx_rdy = 0;
*UART_TX_DATA_ADDR = chr;
// send character stored in uart_tx_addr
*UART_TX_CTRL_ADDR = 1;
// wait until tx is ready again for sening another character
do {
// read uart tx status
tx_rdy = *UART_TX_CTRL_ADDR;
asm volatile ("nop");
} while(!tx_rdy);
#else
uint32_t tx_rdy = 0;
*UART_TX_DATA_ADDR = chr;
// send character stored in uart_tx_addr
*UART_TX_CTRL_ADDR = 1;
// wait until tx is ready again for sening another character
do {
// read uart tx status
tx_rdy = *UART_TX_CTRL_ADDR;
asm volatile ("nop");
} while(!tx_rdy);
#endif
return;
}
================================================
FILE: sw/basic-gpio/uart.h
================================================
#ifndef UART_H
#include <stdint.h>
int sendString(char* str, long len);
void putChr(char chr);
#endif /* UART_H */
================================================
FILE: sw/basic-gpio/util.c
================================================
/*
* utility functions for embedded usage where c-libs are too big
*/
//----------------------------
// integer to ascii (itoa) with util functions
//----------------------------
// function to swap two numbers
void swap(char *x, char *y) {
char t = *x;
*x = *y;
*y = t;
}
// function to reverse buffer[i..j]
char* reverse(char *buffer, int i, int j) {
while (i < j)
swap(&buffer[i++], &buffer[j--]);
return buffer;
}
// Iterative function to implement itoa() function in C
char* itoa(int value, char* buffer, int base) {
// invalid input
if (base < 2 || base > 32)
return buffer;
// consider absolute value of number
int n = (value < 0) ? -value : value;
int i = 0;
while (n) {
int r = n % base;
if (r >= 10)
buffer[i++] = 65 + (r - 10);
else
buffer[i++] = 48 + r;
n = n / base;
}
// if number is 0
if (i == 0)
buffer[i++] = '0';
// If base is 10 and value is negative, the resulting string
// is preceded with a minus sign (-)
// With any other base, value is always considered unsigned
if (value < 0 && base == 10)
buffer[i++] = '-';
buffer[i] = '\0'; // null terminate string
// reverse the string and return it
return reverse(buffer, 0, i - 1);
}
================================================
FILE: sw/basic-gpio/util.h
================================================
#ifndef UTIL_H
void swap(char *x, char *y);
char* reverse(char *buffer, int i, int j);
char* itoa(int value, char* buffer, int base);
#endif /* UTIL_H */
================================================
FILE: sw/basic-multicore/Makefile
================================================
OBJECTS = main.o bootstrap.o
CFLAGS = -march=rv32ima -mabi=ilp32
LDFLAGS = -nostartfiles -Wl,--no-relax
VP = tiny32-mc
VP_FLAGS = --error-on-zero-traphandler=true
include ../Makefile.common
================================================
FILE: sw/basic-multicore/bootstrap.S
================================================
.globl _start
.globl main
.equ SYSCALL_ADDR, 0x02010000
# NOTE: this will exit the whole simulation, i.e. stop all harts
.macro SYS_EXIT, exit_code
li a7, 93
li a0, \exit_code
li t0, SYSCALL_ADDR
csrr a6, mhartid
sw a6, 0(t0)
.endm
# NOTE: each core will start here with execution
_start:
# initialize global pointer (see crt0.S of the RISC-V newlib C-library port)
.option push
.option norelax
1:auipc gp, %pcrel_hi(__global_pointer$)
addi gp, gp, %pcrel_lo(1b)
.option pop
csrr a0, mhartid # return a core specific number 0 or 1
li t0, 0
beq a0, t0, core0
li t0, 1
beq a0, t0, core1
core0:
la sp, stack0_end # code executed only by core0
j end
core1:
la sp, stack1_end # code executed only by core1
j end
end:
jal main
# wait until all two cores have finished
la t0, exit_counter
li t1, 1
li t2, 1
amoadd.w a0, t1, 0(t0)
1:
blt a0, t2, 1b
# call exit (SYS_EXIT=93) with exit code 0 (argument in a0)
SYS_EXIT 0
.align 8
stack0_begin:
.zero 32768
stack0_end:
.align 8
stack1_begin:
.zero 32768
stack1_end:
exit_counter:
.word 0
================================================
FILE: sw/basic-multicore/main.c
================================================
int main(unsigned hart_id) {
// behave differently based on the core (i.e. hart) id
for (unsigned i=0; i<100*hart_id; ++i)
;
return 0;
}
================================================
FILE: sw/blocking-sleep/Makefile
================================================
OBJECTS = main.o irq.o bootstrap.o
CFLAGS = -march=rv32imac -mabi=ilp32
LDFLAGS = -nostartfiles -Wl,--no-relax
VP = tiny32-vp
include ../Makefile.common
================================================
FILE: sw/blocking-sleep/bootstrap.S
================================================
.globl _start
.globl register_handler
.globl main
_start:
call register_handler
jal main
# call exit (SYS_EXIT=93) with exit code 0 (argument in a0)
li a7,93
li a0,0
ecall
================================================
FILE: sw/blocking-sleep/irq.S
================================================
.globl register_handler
.globl lvl0_handler
.align 4
lvl0_handler:
# Store all register values on the stack
addi sp, sp, -4 * 32
sw x1, 0x0(sp)
sw x4, 3 * 4(sp)
sw x5, 4 * 4(sp)
sw x6, 5 * 4(sp)
sw x7, 6 * 4(sp)
sw x10, 9 * 4(sp)
sw x11, 10 * 4(sp)
sw x12, 11 * 4(sp)
sw x13, 12 * 4(sp)
sw x14, 13 * 4(sp)
sw x15, 14 * 4(sp)
sw x16, 15 * 4(sp)
sw x17, 16 * 4(sp)
sw x28, 27 * 4(sp)
sw x29, 28 * 4(sp)
sw x30, 29 * 4(sp)
sw x31, 30 * 4(sp)
jal irq_handler
# Load all register values from the stack and return
lw x1, 0x0(sp)
lw x4, 3 * 4(sp)
lw x5, 4 * 4(sp)
lw x6, 5 * 4(sp)
lw x7, 6 * 4(sp)
lw x10, 9 * 4(sp)
lw x11, 10 * 4(sp)
lw x12, 11 * 4(sp)
lw x13, 12 * 4(sp)
lw x14, 13 * 4(sp)
lw x15, 14 * 4(sp)
lw x16, 15 * 4(sp)
lw x17, 16 * 4(sp)
lw x28, 27 * 4(sp)
lw x29, 28 * 4(sp)
lw x30, 29 * 4(sp)
lw x31, 30 * 4(sp)
addi sp, sp, 4 * 32
mret
register_handler:
# Use lvl0_handler as the trap handler
la t0, lvl0_handler
csrw mtvec, t0
# Enable machine external interrupts (MIE bit)
li t1, 0x888
csrw mie, t1
# Globally enable machine mode interrupts (MIE bit)
li t1, 8
csrw mstatus, t1
# Return
ret
================================================
FILE: sw/blocking-sleep/main.c
================================================
#include <stdint.h>
#include <stdbool.h>
enum {
SLEEP_TIME = 5, // In seconds
US_PER_SEC = 1000000,
};
/* This is used to quantize a 1MHz value to the closest 32768Hz value */
#define DIVIDEND ((uint64_t)15625/(uint64_t)512)
/* Bitmask to extract exception code from mcause register */
#define MCAUSE_CAUSE 0x7FFFFFFF
/* Exception code for timer interrupts */
#define MACHINE_TIMER 7
/* Set after timer interrupt was received */
static volatile bool terminate = false;
static volatile uint64_t *MTIMECMP_REG = (uint64_t *)0x2004000;
static volatile uint64_t *MTIME_REG = (uint64_t *)0x200bff8;
void irq_handler(void) {
uint32_t mcause;
uint32_t code;
mcause = 0;
__asm__ volatile ("csrr %[ret], mcause"
: [ret] "=r" (mcause));
code = mcause & MCAUSE_CAUSE;
if (code != MACHINE_TIMER || terminate)
__asm__ volatile ("ebreak");
// Attempt to clear timer interrupt
*MTIMECMP_REG = UINT64_MAX;
terminate = true;
return;
}
int main() {
uint64_t usec = SLEEP_TIME * US_PER_SEC;
uint64_t ticks = usec / DIVIDEND;
uint64_t target = *MTIME_REG + ticks;
*MTIMECMP_REG = target;
while (!terminate)
__asm__ volatile ("wfi");
return 0;
}
================================================
FILE: sw/busy-wait-sleep/Makefile
================================================
OBJECTS = main.o bootstrap.o
CFLAGS = -march=rv32i -mabi=ilp32
LDFLAGS = -nostartfiles -Wl,--no-relax
VP = tiny32-vp
include ../Makefile.common
================================================
FILE: sw/busy-wait-sleep/bootstrap.S
================================================
.globl _start
.globl main
_start:
jal main
# call exit (SYS_EXIT=93) with exit code 0 (argument in a0)
li a7,93
li a0,0
ecall
================================================
FILE: sw/busy-wait-sleep/main.c
================================================
#include <stdint.h>
static volatile uint64_t *MTIMECMP_REG = (uint64_t *)0x2004000;
static volatile uint64_t *MTIME_REG = (uint64_t *)0x200bff8;
enum {
SLEEP_TIME = 5, // In seconds
US_PER_SEC = 1000000,
};
/* This is used to quantize a 1MHz value to the closest 32768Hz value */
#define DIVIDEND ((uint64_t)15625/(uint64_t)512)
int main() {
uint64_t usec = SLEEP_TIME * US_PER_SEC;
uint64_t ticks = usec / DIVIDEND;
uint64_t target = *MTIME_REG + ticks;
while (*MTIME_REG < target)
;
return 0;
}
================================================
FILE: sw/c++-lib/Makefile
================================================
LD = $(CXX)
OBJECTS = main.o
CXXFLAGS = -std=c++14 -march=rv32imac -mabi=ilp32
include ../Makefile.common
override LD = $(CXX)
================================================
FILE: sw/c++-lib/main.cpp
================================================
#include <iostream>
#include <list>
#include <map>
#include <vector>
struct A {
int a;
int b;
A(int a, int b) : a(a), b(b) {}
virtual int foo() = 0;
virtual int bar() {
return a + b;
}
};
struct B : public A {
using A::A;
virtual int foo() override {
return a - b;
}
};
int main() {
std::cout << "Hello World\n";
B x(5, 2);
auto a = x.foo();
auto b = x.bar();
std::cout << a << "\n";
std::cout << b << "\n";
std::vector<int> v;
v.push_back(1);
v.push_back(2);
for (auto e : v) std::cout << e << std::endl;
return 0;
}
================================================
FILE: sw/clock-ticks/Makefile
================================================
OBJECTS = main.o irq.o bootstrap.o
CFLAGS = -march=rv32imac -mabi=ilp32
LDFLAGS = -nostartfiles -Wl,--no-relax
include ../Makefile.common
================================================
FILE: sw/clock-ticks/bootstrap.S
================================================
.globl _start
.globl main
.globl level_1_interrupt_handler
_start:
la t0, level_0_interrupt_handler
csrw mtvec, t0
li t1, 0x888
csrw mie, t1
csrwi mstatus, 8
jal main
# call exit (SYS_EXIT=93) with exit code 0 (argument in a0)
li a7,93
li a0,0
ecall
/*
* Interrupt handler for non-nested interrupts. Only selected registers are stored/re-stored, i.e. those not preserved on function calls.
*/
#define STORE sw
#define LOAD lw
#define REGBYTES 4
.align 4
level_0_interrupt_handler:
// store execution context on the stack (register content)
addi sp, sp, -REGBYTES * 32
STORE x1, 0x0(sp)
STORE x4, 3 * REGBYTES(sp)
STORE x5, 4 * REGBYTES(sp)
STORE x6, 5 * REGBYTES(sp)
STORE x7, 6 * REGBYTES(sp)
STORE x10, 9 * REGBYTES(sp)
STORE x11, 10 * REGBYTES(sp)
STORE x12, 11 * REGBYTES(sp)
STORE x13, 12 * REGBYTES(sp)
STORE x14, 13 * REGBYTES(sp)
STORE x15, 14 * REGBYTES(sp)
STORE x16, 15 * REGBYTES(sp)
STORE x17, 16 * REGBYTES(sp)
STORE x28, 27 * REGBYTES(sp)
STORE x29, 28 * REGBYTES(sp)
STORE x30, 29 * REGBYTES(sp)
STORE x31, 30 * REGBYTES(sp)
// load interrupt/trap reason and call external C function to handle it
csrr a0, mcause
jal level_1_interrupt_handler
// re-store the saved context
LOAD x1, 0x0(sp)
LOAD x4, 3 * REGBYTES(sp)
LOAD x5, 4 * REGBYTES(sp)
LOAD x6, 5 * REGBYTES(sp)
LOAD x7, 6 * REGBYTES(sp)
LOAD x10, 9 * REGBYTES(sp)
LOAD x11, 10 * REGBYTES(sp)
LOAD x12, 11 * REGBYTES(sp)
LOAD x13, 12 * REGBYTES(sp)
LOAD x14, 13 * REGBYTES(sp)
LOAD x15, 14 * REGBYTES(sp)
LOAD x16, 15 * REGBYTES(sp)
LOAD x17, 16 * REGBYTES(sp)
LOAD x28, 27 * REGBYTES(sp)
LOAD x29, 28 * REGBYTES(sp)
LOAD x30, 29 * REGBYTES(sp)
LOAD x31, 30 * REGBYTES(sp)
addi sp, sp, REGBYTES * 32
mret
================================================
FILE: sw/clock-ticks/irq.c
================================================
#include "irq.h"
#include "assert.h"
#define RISCV_MACHINE_SOFTWARE_INTERRUPT 3
#define RISCV_MACHINE_TIMER_INTERRUPT 7
#define RISCV_MACHINE_EXTERNAL_INTERRUPT 11
#define PLIC_BASE 0x40000000
#define IRQ_TABLE_NUM_ENTRIES 64
static volatile uint32_t * const PLIC_INTERRUPT_ENABLE_START = (uint32_t * const)(PLIC_BASE + 0x2000);
static volatile uint32_t * const PLIC_CLAIM_AND_RESPONSE_REGISTER = (uint32_t * const)(PLIC_BASE + 0x200004);
static void irq_empty_handler() {}
static irq_handler_t irq_handler_table[IRQ_TABLE_NUM_ENTRIES] = { [ 0 ... IRQ_TABLE_NUM_ENTRIES-1 ] = irq_empty_handler };
#define CLINT_BASE 0x2000000
volatile uint64_t* mtime = (uint64_t*)(CLINT_BASE + 0xbff8);
volatile uint64_t* mtimecmp = (uint64_t*)(CLINT_BASE + 0x4000);
static irq_handler_t timer_irq_handler = 0;
void level_1_interrupt_handler(uint32_t cause) {
switch (cause & 0xf) {
case RISCV_MACHINE_EXTERNAL_INTERRUPT: {
asm volatile ("csrc mip, %0" : : "r" (0x800));
uint32_t irq_id = *PLIC_CLAIM_AND_RESPONSE_REGISTER;
irq_handler_table[irq_id]();
*PLIC_CLAIM_AND_RESPONSE_REGISTER = 1;
return;
}
case RISCV_MACHINE_TIMER_INTERRUPT: {
// Note: the pending timer interrupt bit will be automatically cleared when writing to the *mtimecmp* register of this hart
if (timer_irq_handler) {
// let the user registered handler clear the timer interrupt bit
timer_irq_handler();
} else {
// reset the *mtimecmp* register to zero to clear the pending bit
*mtimecmp = 0;
}
return;
}
}
assert (0 && "unsupported cause");
}
void register_interrupt_handler(uint32_t irq_id, irq_handler_t fn) {
assert (irq_id < IRQ_TABLE_NUM_ENTRIES);
// enable interrupt
volatile uint32_t* const reg = (PLIC_INTERRUPT_ENABLE_START + irq_id/32);
*reg |= 1 << (irq_id%32);
// set a prio different to zero (which means do-not-interrupt)
*((uint32_t*) (PLIC_BASE + irq_id*sizeof(uint32_t))) = 1;
irq_handler_table[irq_id] = fn;
}
void register_timer_interrupt_handler(irq_handler_t fn) {
timer_irq_handler = fn;
}
================================================
FILE: sw/clock-ticks/irq.h
================================================
#ifndef __RISCV_IRQ_H__
#define __RISCV_IRQ_H__
#include "stdint.h"
typedef void (*irq_handler_t)(void);
void register_interrupt_handler(uint32_t irq_id, irq_handler_t fn);
void register_timer_interrupt_handler(irq_handler_t fn);
extern volatile uint64_t* mtime;
extern volatile uint64_t* mtimecmp;
#endif
================================================
FILE: sw/clock-ticks/main.c
================================================
#include "stdint.h"
#include "irq.h"
#include "stdio.h"
#include "assert.h"
static void set_next_timer_interrupt() {
assert (mtime && mtimecmp);
*mtimecmp = *mtime + 1000; // 1000 timer ticks, corresponds to 1 MS delay with current CLINT configuration
}
unsigned int num_ticks = 0;
void timer_irq_handler() {
set_next_timer_interrupt();
++num_ticks;
}
int main() {
printf("num_ticks %d\n", num_ticks);
register_timer_interrupt_handler(timer_irq_handler);
set_next_timer_interrupt();
while (num_ticks < 10) {
printf("num_ticks %d\n", num_ticks);
}
printf("num_ticks %d\n", num_ticks);
return 0;
}
================================================
FILE: sw/crc8/Makefile
================================================
OBJECTS = main.o uart.o bootstrap.o
CFLAGS = -march=rv32i -mabi=ilp32
LDFLAGS = -nostartfiles -Wl,--no-relax -T link.ld
VP = microrv32-vp
VP_FLAGS =
hex: all
../elf2bin.py ./main crc.hex 0x4020
include ../Makefile.common
================================================
FILE: sw/crc8/bootstrap.S
================================================
.globl _start
.globl main
.equ SYSCALL_ADDR, 0x02010000
.macro INIT_HW_PLATFORM
and x1,x0,x0
and x2,x0,x0
and x3,x0,x0
and x4,x0,x0
and x5,x0,x0
and x6,x0,x0
and x7,x0,x0
and x8,x0,x0
and x9,x0,x0
and x10,x0,x0
and x11,x0,x0
and x12,x0,x0
and x13,x0,x0
and x14,x0,x0
and x15,x0,x0
and x16,x0,x0
and x17,x0,x0
and x18,x0,x0
and x19,x0,x0
and x20,x0,x0
and x21,x0,x0
and x22,x0,x0
and x23,x0,x0
and x24,x0,x0
and x25,x0,x0
and x26,x0,x0
and x27,x0,x0
and x28,x0,x0
and x29,x0,x0
and x30,x0,x0
and x31,x0,x0
.endm
.macro SYS_EXIT
li a7, 93
li t0, SYSCALL_ADDR
csrr a6, mhartid
sw a6, 0(t0)
.endm
_start:
# initialize hw-platform
INIT_HW_PLATFORM
la sp, stack_end
jal main
# call exit (SYS_EXIT=93) with exit code in a0
SYS_EXIT
stack_begin:
.zero 1024
stack_end:
================================================
FILE: sw/crc8/link.ld
================================================
OUTPUT_ARCH( "riscv" )
ENTRY(_start)
SECTIONS
{
. = 0x80000000;
.text.init : { *(.text.init) }
. = ALIGN(0x1000);
.tohost : { *(.tohost) }
. = ALIGN(0x1000);
.text : { *(.text) }
. = ALIGN(0x1000);
.data : { *(.data) }
.bss : { *(.bss) }
_end = .;
}
================================================
FILE: sw/crc8/main.c
================================================
#include <stdint.h>
#include <stdio.h>
#include "platform.h"
#include "uart.h"
#include "util.h"
// 8-bit SAE J1850 CRC
unsigned char crc8(unsigned char *data, int length) {
/*
* 8-bit CRC calculation
* polynomial : 0x1D
* initial value : 0xFF
* reflect input : no
* reflect result : no
* XOR value : 0xFF
* check : 0x4B
* magic check : 0xC4
*/
unsigned long crc;
int i,bit;
crc = 0xFF;
for(i=0; i<length; i++) {
crc ^= data[i];
for (bit=0; bit<8; bit++) {
if((crc & 0x80)!=0) {
crc <<= 1;
crc ^= 0x1D;
} else {
crc <<= 1;
}
}
}
return (~crc)&0xFF; // xor value = 0xFF
}
int main(int argc, char **argv) {
/*
* test cases from AUTOSAR specification
* 8-bit SAE J1850 CRC
* see : https://www.autosar.org/fileadmin/user_upload/standards/classic/4-3/AUTOSAR_SWS_CRCLibrary.pdf (page 22/50)
* 7.2.1 8-bit CRC calculation
* 7.2.1.1 8-bit SAE J1850 CRC Calculation
*/
// NOTE idea: calculate all 6 test cases in one main loop, see if it makes a good benchmark?
// unsigned char crcData[] = {0x00,0xC0,0xDF,0xAC,0xAA,0x07,0x40}; // 0x6C
// unsigned char crcData[] = {0x00,0x00,0x00,0x00}; // 0x59
// unsigned char crcData[] = {0xF2,0x01,0x83}; // 0x37
const unsigned char crcData[] = {0x33,0x22,0x55,0xAA,0xBB,0xCC,0xDD,0xEE,0xFF}; // 0xCB
// unsigned char crcData[] = {0x92,0x6B,0x55}; // 0x8C
//unsigned char crcData[] = {0xFF,0xFF,0xFF,0xFF}; // 0x74
const unsigned char crcTrueResult = 0xCB;
char buf[3];
char buf2[3];
char *txt1 = "crc8 of:\n";
char *txt2 = "result:\n";
sendString(txt1,10);
for(int i=0; i<sizeof(crcData); i++) {
itoa(crcData[i], buf, 16);
sendString(buf, 3);
}
putChr('\n');
const unsigned char crcResult = crc8((unsigned char*)crcData,sizeof(crcData));
itoa(crcResult, buf2, 16);
sendString(txt2,9);
sendString(buf2, 3);
putChr('\n');
if(crcResult != crcTrueResult) {
sendString("CRC wrong!!!!111!!", 19);
return -1;
} else {
sendString("CRC correct\n", 13);
}
return 0;
}
================================================
FILE: sw/crc8/platform.h
================================================
#ifndef PLATFORM_H
#define PLATFORM_H
//#define MICRORV
#ifdef MICRORV
// LED
static volatile uint32_t *LED_ADDR = (uint32_t *)0x81000000;
// UART
static volatile uint32_t *UART_TX_DATA_ADDR = (uint32_t *)0x82000000;
static volatile uint32_t *UART_TX_CTRL_ADDR = (uint32_t *)0x82000004;
static volatile uint32_t *UART_RX_DATA_ADDR = (uint32_t *)0x82000008;
// CLIC
static volatile uint64_t *MTIMECMP_REG = (uint64_t *)0x02004000;
static volatile uint64_t *MTIME_REG = (uint64_t *)0x0200bff8;
#else
// UART
static volatile uint32_t *UART_TX_DATA_ADDR = (uint32_t *)0x82000000;
static volatile uint32_t *UART_TX_CTRL_ADDR = (uint32_t *)0x82000004;
static volatile uint32_t *UART_RX_DATA_ADDR = (uint32_t *)0x82000008;
// CLIC
static volatile uint64_t *MTIMECMP_REG = (uint64_t *)0x02004000;
static volatile uint64_t *MTIME_REG = (uint64_t *)0x0200bff8;
#endif
#endif /* PLATFORM_H */
================================================
FILE: sw/crc8/uart.c
================================================
#include "uart.h"
#include "platform.h"
#include <stdint.h>
int sendString(char* str, long len) {
long cnt = len;
const char *s = (const char *)str;
while (cnt > 0) {
--cnt;
putChr(*s);
s++;
}
return len;
}
void putChr(char chr) {
#ifdef MICRORV
uint32_t tx_rdy = 0;
*UART_TX_ADDR = chr;
// send character stored in uart_tx_addr
*UART_TX_CTRL = 1;
// wait until tx is ready again for sening another character
do {
// read uart tx status
tx_rdy = *UART_TX_CTRL;
asm volatile ("nop");
} while(!tx_rdy);
#else
uint32_t tx_rdy = 0;
*UART_TX_DATA_ADDR = chr;
// send character stored in uart_tx_addr
*UART_TX_CTRL_ADDR = 1;
// wait until tx is ready again for sening another character
do {
// read uart tx status
tx_rdy = *UART_TX_CTRL_ADDR;
asm volatile ("nop");
} while(!tx_rdy);
#endif
return;
}
================================================
FILE: sw/crc8/uart.h
================================================
#ifndef UART_H
#include <stdint.h>
int sendString(char* str, long len);
void putChr(char chr);
#endif /* UART_H */
================================================
FILE: sw/crc8/util.c
================================================
/*
* utility functions for embedded usage where c-libs are too big
*/
//----------------------------
// integer to ascii (itoa) with util functions
//----------------------------
// function to swap two numbers
void swap(char *x, char *y) {
char t = *x;
*x = *y;
*y = t;
}
// function to reverse buffer[i..j]
char* reverse(char *buffer, int i, int j) {
while (i < j)
swap(&buffer[i++], &buffer[j--]);
return buffer;
}
// Iterative function to implement itoa() function in C
char* itoa(int value, char* buffer, int base) {
// invalid input
if (base < 2 || base > 32)
return buffer;
// consider absolute value of number
int n = (value < 0) ? -value : value;
int i = 0;
while (n) {
int r = n % base;
if (r >= 10)
buffer[i++] = 65 + (r - 10);
else
buffer[i++] = 48 + r;
n = n / base;
}
// if number is 0
if (i == 0)
buffer[i++] = '0';
// If base is 10 and value is negative, the resulting string
// is preceded with a minus sign (-)
// With any other base, value is always considered unsigned
if (value < 0 && base == 10)
buffer[i++] = '-';
buffer[i] = '\0'; // null terminate string
// reverse the string and return it
return reverse(buffer, 0, i - 1);
}
================================================
FILE: sw/crc8/util.h
================================================
#ifndef UTIL_H
void swap(char *x, char *y);
char* reverse(char *buffer, int i, int j);
char* itoa(int value, char* buffer, int base);
#endif /* UTIL_H */
================================================
FILE: sw/flashTest/Makefile
================================================
OBJECTS = main.o
CXXFLAGS = -ggdb -std=c++14 -march=rv32ima -mabi=ilp32
include ../Makefile.common
override LD = $(CXX)
================================================
FILE: sw/flashTest/main.cpp
================================================
#include <inttypes.h>
#include <string.h>
#include <iostream>
// From flash.h
static constexpr unsigned int BLOCKSIZE = 512;
static constexpr unsigned int FLASH_ADDR_REG = 0;
static constexpr unsigned int FLASH_SIZE_REG = sizeof(uint64_t);
static constexpr unsigned int DATA_ADDR = FLASH_SIZE_REG + sizeof(uint64_t);
// static constexpr unsigned int ADDR_SPACE = DATA_ADDR + BLOCKSIZE;
static uint8_t* volatile const FLASH_CONTROLLER = (uint8_t * volatile const)(0x71000000);
using namespace std;
void setTargetBlock(uint64_t addr);
void readFlash(char* dst, uint64_t addr, size_t len);
void writeFlash(const char* src, uint64_t addr, size_t len);
int main() {
unsigned long counter = 0;
uint64_t flashNumOfBlocks = 0;
memcpy(&flashNumOfBlocks, FLASH_CONTROLLER + FLASH_SIZE_REG, sizeof(uint64_t));
cout << "Flash size: " << flashNumOfBlocks * BLOCKSIZE << " (" << flashNumOfBlocks << " Blocks)" << endl;
readFlash(reinterpret_cast<char*>(&counter), 0, sizeof(unsigned long));
cout << " Counter before: " << counter << endl;
writeFlash(reinterpret_cast<char*>(&++counter), 0, sizeof(unsigned long));
cout << " Counter after: " << counter << endl;
}
void setTargetBlock(uint64_t addr) {
uint64_t targetBlock = addr % BLOCKSIZE;
memcpy(FLASH_CONTROLLER + FLASH_ADDR_REG, &targetBlock, sizeof(uint64_t));
}
void readFlash(char* dst, uint64_t addr, size_t len) {
if (addr / BLOCKSIZE != (addr + len) / BLOCKSIZE) {
cerr << "Unaligned read, currently not supported" << endl;
return;
}
setTargetBlock(addr);
memcpy(dst, FLASH_CONTROLLER + DATA_ADDR, len);
}
void writeFlash(const char* src, uint64_t addr, size_t len) {
if (addr / BLOCKSIZE != (addr + len) / BLOCKSIZE) {
cerr << "Unaligned read, currently not supported" << endl;
return;
}
setTargetBlock(addr);
memcpy(FLASH_CONTROLLER + DATA_ADDR, src, len);
}
================================================
FILE: sw/flashTest/test-ignore
================================================
================================================
FILE: sw/mramTest/Makefile
================================================
OBJECTS = main.o
CXXFLAGS = -ggdb -std=c++14 -march=rv32ima -mabi=ilp32
include ../Makefile.common
override LD = $(CXX)
================================================
FILE: sw/mramTest/main.cpp
================================================
#include <string.h>
#include "stdio.h"
static char* const MRAM_START_ADDR = reinterpret_cast<char* const>(0x60000000);
static const unsigned int MRAM_SIZE = 0x0FFFFFFF;
int main() {
unsigned long counter = 0;
char buffer[10] = {0};
memcpy(&counter, MRAM_START_ADDR, sizeof(unsigned long));
memcpy(buffer, MRAM_START_ADDR + 10, 10);
printf("Before:\n");
printf("%lu, %0.*s\n", counter, 10, buffer);
memcpy(MRAM_START_ADDR, &(++counter), sizeof(unsigned long));
memcpy(MRAM_START_ADDR + 10, "Kokosnuss", 10);
memcpy(&counter, MRAM_START_ADDR, sizeof(unsigned long));
memcpy(buffer, MRAM_START_ADDR + 10, 10);
printf("After:\n");
printf("%lu, %0.*s\n", counter, 10, buffer);
}
================================================
FILE: sw/mrv32-uart/Makefile
================================================
rvArch?=rv32i
OBJECTS = bootstrap.o main.o uart.o util.o
CFLAGS = -march=$(rvArch) -mabi=ilp32 -mno-strict-align
LDFLAGS = -nostartfiles -Wl,--no-relax,--print-memory-usage -T link.ld
VP = microrv32-vp
VP_FLAGS =
include ../Makefile.common
================================================
FILE: sw/mrv32-uart/bootstrap.S
================================================
.globl _start
.globl main
.equ SYSCALL_ADDR, 0x02010000
.macro INIT_HW_PLATFORM
and x1,x0,x0
and x2,x0,x0
and x3,x0,x0
and x4,x0,x0
and x5,x0,x0
and x6,x0,x0
and x7,x0,x0
and x8,x0,x0
and x9,x0,x0
and x10,x0,x0
and x11,x0,x0
and x12,x0,x0
and x13,x0,x0
and x14,x0,x0
and x15,x0,x0
and x16,x0,x0
and x17,x0,x0
and x18,x0,x0
and x19,x0,x0
and x20,x0,x0
and x21,x0,x0
and x22,x0,x0
and x23,x0,x0
and x24,x0,x0
and x25,x0,x0
and x26,x0,x0
and x27,x0,x0
and x28,x0,x0
and x29,x0,x0
and x30,x0,x0
and x31,x0,x0
.endm
.macro SYS_EXIT, exit_code
li a7, 93
li a0, \exit_code
li t0, SYSCALL_ADDR
csrr a6, mhartid
sw a6, 0(t0)
sw a7, 0(t0)
.endm
.align 4
_start:
# initialize hw-platform
INIT_HW_PLATFORM
la sp, stack_end
jal main
# call exit (SYS_EXIT=93) with exit code 0 (argument in a0)
1: SYS_EXIT 0
j 1b
.align 4
stack_begin:
.zero 2048
stack_end:
================================================
FILE: sw/mrv32-uart/link.ld
================================================
OUTPUT_ARCH( "riscv" )
ENTRY(_start)
MEMORY {
RAM (rwx): ORIGIN = 0x80000000, LENGTH = 8k
}
SECTIONS
{
. = 0x80000000;
.text.init : { *(.text.init) } > RAM
. = ALIGN(0x1000);
.tohost : { *(.tohost) } > RAM
. = ALIGN(0x1000);
.text : { *(.text) } > RAM
. = ALIGN(0x1000);
.data : { *(.data) } > RAM
.bss : { *(.bss) } > RAM
_end = .;
}
================================================
FILE: sw/mrv32-uart/main.c
================================================
#include <stdint.h>
#include <stdio.h>
// #include <string.h>
#include "platform.h"
#include "uart.h"
#include "util.h"
void delay(uint32_t loops) {
for(uint32_t i = 0; i < loops; i++) {
asm volatile("nop");
}
}
int main() {
delay(10000);
char buf[3];
char *txt1 = "uart rx failed?!\n";
delay(5000);
// delay(7000);
// delay(2000);
// delay(10000);
char rxBuf[5];
int rxEmpty = 1;
int maxCnt = 30;
int cnt = 0;
rxEmpty = UART->RXEMPT;
int occ;
if(!rxEmpty) {
// read rx data register from uart peripheral
do {
rxBuf[0] = UART->RXDATA;
putChr(rxBuf[0]);
cnt++;
occ = UART->RXOCCU;
// sendString()
} while(UART->RXEMPT || cnt <= maxCnt);
putChr('\n');
putChr('\n');
} else {
sendString(txt1,1600);
putChr('\n');
}
return 0;
}
================================================
FILE: sw/mrv32-uart/platform.h
================================================
#ifndef PLATFORM_H
#define PLATFORM_H
/* #define MICRORV
// #ifdef MICRORV */
// LED
static volatile uint32_t *LED_ADDR = (uint32_t *)0x81000000;
// UART
static volatile uint32_t *UART_TX_DATA_ADDR = (uint32_t *)0x82000000;
static volatile uint32_t *UART_TX_CTRL_ADDR = (uint32_t *)0x82000004;
static volatile uint32_t *UART_RX_DATA_ADDR = (uint32_t *)0x82000008;
// CLIC
static volatile uint64_t *MTIMECMP_REG = (uint64_t *)0x02004000;
static volatile uint64_t *MTIME_REG = (uint64_t *)0x0200bff8;
typedef struct {
volatile uint32_t TXDATA;
volatile uint32_t TXCTRL;
volatile uint32_t RXDATA;
volatile uint32_t RXOCCU;
volatile uint32_t RXALEM;
volatile uint32_t RXEMPT;
} UART_REGS;
#define UART ((UART_REGS *)0x82000000)
/* #else
// // UART
// static volatile uint32_t *UART_TX_DATA_ADDR = (uint32_t *)0x82000000;
// static volatile uint32_t *UART_TX_CTRL_ADDR = (uint32_t *)0x82000004;
// static volatile uint32_t *UART_RX_DATA_ADDR = (uint32_t *)0x82000008;
// static volatile uint32_t *UART_RX_FIFO_OCC_ADDR = (uint32_t *)0x8200000c;
// static volatile uint32_t *UART_RX_FIFO_ALMOST_EMPTY_ADDR = (uint32_t *)0x82000010;
// static volatile uint32_t *UART_RX_FIFO_EMPTY_ADDR = (uint32_t *)0x82000014;
// // CLIC
// static volatile uint64_t *MTIMECMP_REG = (uint64_t *)0x02004000;
// static volatile uint64_t *MTIME_REG = (uint64_t *)0x0200bff8;
// #endif */
#endif /* PLATFORM_H */
================================================
FILE: sw/mrv32-uart/uart.c
================================================
#include "uart.h"
#include "platform.h"
#include <stdint.h>
int sendString(char* str, long len) {
long cnt = len;
const char *s = (const char *)str;
while (cnt > 0) {
--cnt;
putChr(*s);
s++;
}
return len;
}
void putChr(char chr) {
uint32_t tx_rdy = 0;
UART->TXDATA = chr;
// send character stored in uart_tx_addr
UART->TXCTRL = 1;
// wait until tx is ready again for sening another character
do {
// read uart tx status
tx_rdy = UART->TXCTRL;
asm volatile ("nop");
} while(!tx_rdy);
return;
}
================================================
FILE: sw/mrv32-uart/uart.h
================================================
#ifndef UART_H
#include <stdint.h>
int sendString(char* str, long len);
void putChr(char chr);
#endif /* UART_H */
================================================
FILE: sw/mrv32-uart/util.c
================================================
/*
* utility functions for embedded usage where c-libs are too big
*/
//----------------------------
// integer to ascii (itoa) with util functions
//----------------------------
// function to swap two numbers
void swap(char *x, char *y) {
char t = *x;
*x = *y;
*y = t;
}
// function to reverse buffer[i..j]
char* reverse(char *buffer, int i, int j) {
while (i < j)
swap(&buffer[i++], &buffer[j--]);
return buffer;
}
// Iterative function to implement itoa() function in C
char* itoa(int value, char* buffer, int base) {
// invalid input
if (base < 2 || base > 32)
return buffer;
// consider absolute value of number
int n = (value < 0) ? -value : value;
int i = 0;
while (n) {
int r = n % base;
if (r >= 10)
buffer[i++] = 65 + (r - 10);
else
buffer[i++] = 48 + r;
n = n / base;
}
// if number is 0
if (i == 0)
buffer[i++] = '0';
// If base is 10 and value is negative, the resulting string
// is preceded with a minus sign (-)
// With any other base, value is always considered unsigned
if (value < 0 && base == 10)
buffer[i++] = '-';
buffer[i] = '\0'; // null terminate string
// reverse the string and return it
return reverse(buffer, 0, i - 1);
}
================================================
FILE: sw/mrv32-uart/util.h
================================================
#ifndef UTIL_H
void swap(char *x, char *y);
char* reverse(char *buffer, int i, int j);
char* itoa(int value, char* buffer, int base);
#endif /* UTIL_H */
================================================
FILE: sw/peripheral-in-the-loop/Makefile
================================================
OBJECTS = main.o irq.o bootstrap.o
CFLAGS = -march=rv32i -mabi=ilp32
LDFLAGS = -nostartfiles -Wl,--no-relax
virtual-bus-path=../../vp/src/platform/hwitl/virtual-bus
simple-sensor-path=../simple-sensor
tty=/dev/ttyUSB2
$(virtual-bus-path)/responder-cli:
make -C $(virtual-bus-path) responder-cli
sim-bus: $(EXECUTABLE) $(virtual-bus-path)/responder-cli
make -C $(virtual-bus-path) pipe_left
sleep 1 #needed sometimes as pipe is not immediately there
$(virtual-bus-path)/responder-cli $(virtual-bus-path)/pipe_right &
hwitl-vp $(EXECUTABLE) --error-on-zero-traphandler=true --virtual-bus-device $(virtual-bus-path)/pipe_left
killall responder-cli
killall socat
real: $(EXECUTABLE)
hwitl-vp $(EXECUTABLE) --error-on-zero-traphandler=true --virtual-bus-device $(tty)
clearpipes:
killall responder-cli || true
killall socat || true
SIM_TARGET = sim-bus
include ../Makefile.common
================================================
FILE: sw/peripheral-in-the-loop/main.c
================================================
#include <stdint.h>
#include "../simple-sensor/irq.h"
typedef uint32_t BUS_BRIDGE_TYPE;
static volatile BUS_BRIDGE_TYPE * const BUS_BRIDGE_START = (BUS_BRIDGE_TYPE * const) 0x50000000;
static volatile BUS_BRIDGE_TYPE * const BUS_BRIDGE_END = (BUS_BRIDGE_TYPE * const) 0x5000000F; // INCLUSIVE
static const unsigned BUS_BRIDGE_ITR = 2;
static volatile char * const TERMINAL_ADDR = (char * const)0x20000000;
static const unsigned num_words = (BUS_BRIDGE_END - BUS_BRIDGE_START) + 1; // INCLUSIVE
void read_stuff() {
for (int i = 0; i < num_words; i++) {
const BUS_BRIDGE_TYPE datum = BUS_BRIDGE_START[i];
for(int c = 0; c < sizeof(BUS_BRIDGE_TYPE); c++) {
*TERMINAL_ADDR = ((uint8_t*)&datum)[c];
}
*TERMINAL_ADDR = '\n';
}
}
void write_stuff() {
for (int i = 0; i < num_words; i++) {
BUS_BRIDGE_TYPE datum;
for(int c = 0; c < sizeof(BUS_BRIDGE_TYPE); c++) {
((uint8_t*)&datum)[c] = 'a' + (i+c);
*TERMINAL_ADDR = ((uint8_t*)&datum)[c];
}
BUS_BRIDGE_START[i] = datum;
*TERMINAL_ADDR = '\n';
}
}
volatile int was_itr_triggered = 0;
void virtual_bus_irq_handler() {
static const char* hi = "Interrupt was triggered\n";
was_itr_triggered = 1;
for(int i = 0; hi[i]; i++)
*TERMINAL_ADDR = hi[i];
}
int main() {
register_interrupt_handler(BUS_BRIDGE_ITR, virtual_bus_irq_handler);
read_stuff();
/*
while(!was_itr_triggered)
asm volatile ("wfi");
*/
write_stuff();
return 0;
}
================================================
FILE: sw/printf/Makefile
================================================
OBJECTS = main.o entry.o
CFLAGS = -march=rv32i -mabi=ilp32
LDFLAGS = -Wl,-e_reset_vector
VP_FLAGS = --error-on-zero-traphandler=true
include ../Makefile.common
================================================
FILE: sw/printf/entry.S
================================================
.globl _start
.globl _reset_vector
.equ SYSCALL_ADDR, 0x02010000
trap_handler:
li t0, SYSCALL_ADDR
csrr t1, mhartid
sw t1, 0(t0)
csrr t0, mepc
addi t0, t0, 4
csrw mepc, t0
mret
_reset_vector:
la t0, trap_handler
csrw mtvec, t0
j _start
================================================
FILE: sw/printf/main.c
================================================
#include "stdio.h"
#include "errno.h"
#include "string.h"
#include "unistd.h"
int main(int argc, char **argv) {
int n = printf("ABCDEFX %s\n", "Done");
int e = errno;
puts(strerror(e));
puts ("Hello World!");
puts (" Hello World!");
puts (" X A ");
putchar('a');
putchar('b');
putchar('c');
putchar('\n');
printf(" X Test\n");
printf("%d\n", 12);
printf("Should print 1.2: %f\n", 1.2f);
return 0;
}
================================================
FILE: sw/simple-display/Makefile
================================================
OBJECTS = main.o libDisplay.o
CXXFLAGS = -std=c++14 -march=rv32ima -mabi=ilp32
removeSHMEM:
ipcrm --shmem-key 0x0000053a || true
include ../Makefile.common
override LD = $(CXX)
================================================
FILE: sw/simple-display/libDisplay.cpp
================================================
/*
* libDisplay.cpp
*
* Created on: Oct 5, 2018
* Author: dwd
*/
#include "libDisplay.hpp"
#include <math.h>
#include <algorithm>
typedef Framebuffer::Point Point;
typedef Framebuffer::PointF PointF;
typedef Framebuffer::Color Color;
namespace display {
void setPixel(Framebuffer::Type frame, Point pixel, Color color) {
framebuffer->getFrame(frame).raw[pixel.y][pixel.x] = color;
}
void drawLine(Framebuffer::Type frame, PointF from, PointF to, Color color) {
framebuffer->parameter.line.frame = frame;
framebuffer->parameter.line.from = from;
framebuffer->parameter.line.to = to;
framebuffer->parameter.line.color = color;
framebuffer->command = Framebuffer::Command::drawLine;
}
void drawRect(Framebuffer::Type frame, PointF ol, PointF ur, Color color) {
if (ol.x > ur.x) {
std::swap(ol.x, ur.x);
}
if (ol.y > ur.y) {
std::swap(ol.y, ur.y);
}
drawLine(frame, ol, PointF(ur.x, ol.y), color);
drawLine(frame, PointF(ur.x, ol.y), ur, color);
drawLine(frame, ur, PointF(ol.x, ur.y), color);
drawLine(frame, PointF(ol.x, ur.y), ol, color);
}
void fillRect(Framebuffer::Type frame, PointF ol, PointF ur, Color color) {
if (ol.x == ur.x || ol.y == ur.y) { // No dimension
return;
}
if (ol.x > ur.x) {
std::swap(ol.x, ur.x);
}
if (ol.y > ur.y) {
std::swap(ol.y, ur.y);
}
if (ur.x - ol.x > ur.y - ol.y) {
// Horizontal
for (uint16_t y = ol.y; y <= ur.y; y++) {
drawLine(frame, PointF(ol.x, y), PointF(ur.x, y), color);
}
} else {
// Vertical
for (uint16_t x = ol.x; x <= ur.x; x++) {
drawLine(frame, PointF(x, ol.y), PointF(x, ur.y), color);
}
}
}
void applyFrame() {
framebuffer->command = Framebuffer::Command::applyFrame;
}
void fillFrame(Framebuffer::Type frame, Color color) {
framebuffer->parameter.fill.frame = frame;
framebuffer->parameter.fill.color = color;
framebuffer->command = Framebuffer::Command::fillFrame;
}
} // namespace display
================================================
FILE: sw/simple-display/libDisplay.hpp
================================================
/*
* libDisplay.hpp
*
* Created on: Oct 5, 2018
* Author: dwd
*/
#pragma once
#include "../../env/basic/vp-display/framebuffer.h"
extern Framebuffer* volatile const framebuffer;
inline Framebuffer::Color fromRGB(uint8_t r, uint8_t g, uint8_t b) {
Framebuffer::Color ret = 0;
ret |= (b & 0x0F);
ret |= (g & 0x0F) << 4;
ret |= (r & 0x0F) << 8;
return ret;
}
namespace display {
void setPixel(Framebuffer::Type frame, Framebuffer::Point pixel, Framebuffer::Color color);
void drawLine(Framebuffer::Type frame, Framebuffer::PointF from, Framebuffer::PointF to, Framebuffer::Color color);
void drawRect(Framebuffer::Type frame, Framebuffer::PointF ol, Framebuffer::PointF ur, Framebuffer::Color color);
void fillRect(Framebuffer::Type frame, Framebuffer::PointF ol, Framebuffer::PointF ur, Framebuffer::Color color);
void applyFrame();
void fillFrame(Framebuffer::Type frame = Framebuffer::Type::foreground, Framebuffer::Color color = 0);
}; // namespace display
================================================
FILE: sw/simple-display/main.cpp
================================================
#include "libDisplay.hpp"
#include <math.h>
#include <climits>
#include <cstring>
#include <iostream>
Framebuffer* volatile const framebuffer = (Framebuffer * volatile const)(0x72000000);
typedef Framebuffer::Point Point;
typedef Framebuffer::PointF PointF;
typedef Framebuffer::Color Color;
static constexpr auto screenWidth = Framebuffer::screenWidth;
static constexpr auto screenHeight = Framebuffer::screenHeight;
void activeWait(float factor = 0.5) {
for (uint16_t i = 0; i < UINT16_MAX * factor; i++) {
};
}
Point getRandomPoint() {
return Point(rand() % screenWidth, rand() % screenHeight);
}
Color getRandomColor() {
return rand() % SHRT_MAX;
}
void drawBackground() {
for (uint32_t i = 0; i < screenHeight - 1; i++) {
display::drawLine(Framebuffer::Type::background, Point(0, i), Point(screenWidth, i),
fromRGB(i & 0x7, 0, i >> 3));
if (i % 5 == 0)
display::applyFrame();
}
}
void drawFunnyRects() {
static uint32_t m = 0;
for (uint16_t i = 0; i < 400; i++) {
// drawLine(framebuffer->getInactiveFrame(), getRandomPoint(),
// getRandomPoint(), getRandomColor());
display::drawRect(Framebuffer::Type::foreground, Point(m % screenWidth, m % screenHeight),
Point(
(screenWidth - (m + 1) % screenWidth), (screenHeight - (m + 1) % screenHeight)
),
fromRGB(255 - (m % 255), (m % 255), i % 255));
display::applyFrame();
activeWait(.005);
m += 17;
}
}
/**
* @param completion Values between 0..1
*/
void progressBar(bool horizontal, Framebuffer::PointF base, Framebuffer::PointF extent, Color fg, Color bg, float completion) {
PointF progress = horizontal ? PointF(extent.x * completion, extent.y) : PointF(extent.x, extent.y * completion);
display::fillRect(Framebuffer::Type::foreground, base, base + progress, fg);
display::fillRect(Framebuffer::Type::foreground, base + progress, base + extent, bg);
}
void drawFunnyBar(bool horizontal = false) {
Color bgColor = fromRGB(0, 0, 1);
Color progressColor = fromRGB(126, 255, 10);
Point baseOL;
Point baseUR;
uint16_t stepsize = 1;
if (horizontal) {
baseOL = Point(100, 250);
baseUR = Point(700, 350);
} else {
baseOL = Point(350, 50);
baseUR = Point(450, 550);
}
display::fillRect(Framebuffer::Type::foreground, baseOL, baseUR, bgColor);
display::applyFrame();
Point barBase(baseOL.x + 10, baseOL.y + 10);
Point barExtent((baseUR.x - baseOL.x) - 20, (baseUR.y - baseOL.y) - 20);
for (float progress = 0; progress <= 1; progress += 0.01) {
display::fillRect(Framebuffer::Type::foreground, baseOL, baseUR, bgColor);
progressBar(horizontal, barBase, barExtent, progressColor, bgColor, progress);
display::applyFrame();
activeWait(.005);
}
for (float progress = 1; progress >= 0; progress -= 0.01) {
display::fillRect(Framebuffer::Type::foreground, baseOL, baseUR, bgColor);
progressBar(horizontal, barBase, barExtent, progressColor, bgColor, progress);
display::applyFrame();
activeWait(.005);
}
}
using namespace std;
int main() {
cout << "draw background" << endl;
drawBackground();
while (true) {
cout << "Draw H-bar" << endl;
drawFunnyBar(true);
display::fillFrame(Framebuffer::Type::foreground);
display::applyFrame();
cout << "Draw V-bar" << endl;
drawFunnyBar(false);
display::fillFrame(Framebuffer::Type::foreground);
display::applyFrame();
cout << "Draw Rects" << endl;
drawFunnyRects();
display::fillFrame(Framebuffer::Type::foreground);
display::applyFrame();
}
return 0;
}
================================================
FILE: sw/simple-display/test-ignore
================================================
================================================
FILE: sw/simple-scheduler/Makefile
================================================
OBJECTS = main.o cor.o
CFLAGS = -march=rv32imac -mabi=ilp32
include ../Makefile.common
================================================
FILE: sw/simple-scheduler/cor.S
================================================
.globl contextswitch
.globl coroutine_entry
.globl launch_coroutine
coroutine_entry:
// move the launch argument to the a0 register (i.e. first argument of the following function)
mv a0,s0
call launch_coroutine
// the above call should not return (i.e the scheduler should not call a finished coroutine)
ebreak
/*
* registers a0 and a1 point to the current and next context, respectively
*
* 1) store all current registers and pc in the current context
* 2) load register values from next context
* 3) jump to pc in the next context
*/
contextswitch:
// store registers
sw x1,4(a0) // ra
sw x2,8(a0) // sp
sw x8,32(a0) // s0
sw x9,36(a0) // s1
sw x18,72(a0) // s2
sw x19,76(a0) // s3
sw x20,80(a0) // s4
sw x21,84(a0) // s5
sw x22,88(a0) // s6
sw x23,92(a0) // s7
sw x24,96(a0) // s8
sw x25,100(a0) // s9
sw x26,104(a0) // s10
sw x27,108(a0) // s11
// store pc
la t0,_resume
sw t0,0(a0)
// restore other registers (NOTE: callee saved only + ra)
lw x1,4(a1) // ra
lw x2,8(a1) // sp
lw x8,32(a1) // s0
lw x9,36(a1) // s1
lw x18,72(a1) // s2
lw x19,76(a1) // s3
lw x20,80(a1) // s4
lw x21,84(a1) // s5
lw x22,88(a1) // s6
lw x23,92(a1) // s7
lw x24,96(a1) // s8
lw x25,100(a1) // s9
lw x26,104(a1) // s10
lw x27,108(a1) // s11
// load new program counter and perform context switch
lw t0,0(a1)
jr t0
_resume:
ret
================================================
FILE: sw/simple-scheduler/main.c
================================================
#include <stdlib.h>
#include <stdio.h>
#include <assert.h>
#include <stdint.h>
#define REG_SP 1
#define REG_S0 7
typedef void (*entrypoint_t)(void *);
enum state_t {
UNKNOWN,
START,
ACTIVE,
FINISHED
};
typedef struct {
uint32_t pc;
uint32_t regs[31];
} context_t;
typedef struct {
uint8_t stack[16384];
context_t ctx;
entrypoint_t entry;
void *arg;
enum state_t stat;
} coroutine_t;
context_t main_context;
context_t *active_context;
extern void contextswitch(context_t *current, context_t *next);
extern void coroutine_entry();
void switch_to_scheduler() {
contextswitch(active_context, &main_context);
}
void switch_to_coroutine(coroutine_t *cor) {
active_context = &cor->ctx;
contextswitch(&main_context, &cor->ctx);
}
void launch_coroutine(coroutine_t *cor) {
cor->stat = ACTIVE;
cor->entry(cor->arg);
cor->stat = FINISHED;
assert (active_context == &cor->ctx);
switch_to_scheduler();
}
void function_A(void *arg) {
printf("A fn: 1\n");
switch_to_scheduler();
printf("A fn: 2\n");
}
void function_B(void *arg) {
printf("B fn: 1\n");
switch_to_scheduler();
printf("B fn: 2\n");
switch_to_scheduler();
printf("B fn: 3\n");
}
coroutine_t *create_coroutine(entrypoint_t fn, void *arg) {
coroutine_t *cor = (coroutine_t *)malloc(sizeof(coroutine_t));
for (int i=0; i<31; ++i)
cor->ctx.regs[i] = 0;
cor->ctx.regs[REG_SP] = (uint32_t)(&cor->stack[16384]);
cor->ctx.regs[REG_S0] = (uint32_t)cor;
cor->entry = fn;
cor->arg = arg;
cor->stat = START;
cor->ctx.pc = (uint32_t)coroutine_entry;
return cor;
}
void free_coroutine(coroutine_t *cor) {
free(cor);
}
int main() {
coroutine_t *A_cor = create_coroutine(function_A, 0);
coroutine_t *B_cor = create_coroutine(function_B, 0);
_Bool done = 0;
while (!done) {
done = 1;
if (A_cor->stat != FINISHED) {
switch_to_coroutine(A_cor);
done = 0;
}
if (B_cor->stat != FINISHED) {
switch_to_coroutine(B_cor);
done = 0;
}
}
free_coroutine(A_cor);
free_coroutine(B_cor);
return 0;
}
================================================
FILE: sw/simple-scheduler/no-clib/Makefile
================================================
all : main.c
riscv32-unknown-elf-gcc main.c cor.S bootstrap.S -o main -march=rv32ima -mabi=ilp32 -nostartfiles
sim: all
riscv-vp --intercept-syscalls main
dump-elf: all
riscv32-unknown-elf-readelf -a main
dump-code: all
riscv32-unknown-elf-objdump -D main
clean:
rm -f main
================================================
FILE: sw/simple-scheduler/no-clib/bootstrap.S
================================================
.globl _start
.globl main
_start:
# Initialize global pointer
.option push
.option norelax
1:auipc gp, %pcrel_hi(__global_pointer$)
addi gp, gp, %pcrel_lo(1b)
.option pop
li sp, 8000000
jal main
# call exit (SYS_EXIT=93) with exit code 0 (argument in a0)
li a7,93
li a0,0
ecall
================================================
FILE: sw/simple-scheduler/no-clib/cor.S
================================================
.globl contextswitch
.globl coroutine_entry
.globl launch_coroutine
coroutine_entry:
// move the launch argument to the a0 register (i.e. first argument of the following function)
mv a0,s0
call launch_coroutine
// the above call should not return (i.e the scheduler should not call a finished coroutine)
ebreak
/*
* registers a0 and a1 point to the current and next context, respectively
*
* 1) store all current registers and pc in the current context
* 2) load register values from next context
* 3) jump to pc in the next context
*/
contextswitch:
// store registers
sw x1,4(a0) // ra
sw x2,8(a0) // sp
//sw x3,12(a0) // gp
//sw x4,16(a0) // tp
//sw x5,20(a0) // t0
//sw x6,24(a0) // t1
//sw x7,28(a0) // t2
sw x8,32(a0) // s0
sw x9,36(a0) // s1
//sw x10,40(a0) // a0
//sw x11,44(a0) // a1
//sw x12,48(a0) // a2
//sw x13,52(a0) // a3
//sw x14,56(a0) // a4
//sw x15,60(a0) // a5
//sw x16,64(a0) // a6
//sw x17,68(a0) // a7
sw x18,72(a0) // s2
sw x19,76(a0) // s3
sw x20,80(a0) // s4
sw x21,84(a0) // s5
sw x22,88(a0) // s6
sw x23,92(a0) // s7
sw x24,96(a0) // s8
sw x25,100(a0) // s9
sw x26,104(a0) // s10
sw x27,108(a0) // s11
//sw x28,112(a0) // t3
//sw x29,116(a0) // t4
//sw x30,120(a0) // t5
//sw x31,124(a0) // t6
// store pc
la t0,_resume
sw t0,0(a0)
// restore other registers (NOTE: callee saved only + ra)
lw x1,4(a1) // ra
lw x2,8(a1) // sp
lw x8,32(a1) // s0
lw x9,36(a1) // s1
lw x18,72(a1) // s2
lw x19,76(a1) // s3
lw x20,80(a1) // s4
lw x21,84(a1) // s5
lw x22,88(a1) // s6
lw x23,92(a1) // s7
lw x24,96(a1) // s8
lw x25,100(a1) // s9
lw x26,104(a1) // s10
lw x27,108(a1) // s11
// load new program counter and perform context switch
lw t0,0(a1)
jr t0
_resume:
ret
================================================
FILE: sw/simple-scheduler/no-clib/main.c
================================================
#include "stdlib.h"
#include "stdio.h"
#include "assert.h"
#define REG_SP 1
#define REG_S0 7
typedef void (*entrypoint_t)(void *);
enum state_t {
UNKNOWN,
START,
ACTIVE,
FINISHED
};
typedef struct {
uint32_t pc;
uint32_t regs[31];
} context_t;
typedef struct {
uint8_t stack[16384];
context_t ctx;
entrypoint_t entry;
void *arg;
enum state_t stat;
} coroutine_t;
context_t main_context;
context_t *active_context;
extern void contextswitch(context_t *current, context_t *next);
extern void coroutine_entry();
void switch_to_scheduler() {
contextswitch(active_context, &main_context);
}
void switch_to_coroutine(coroutine_t *cor) {
active_context = &cor->ctx;
contextswitch(&main_context, &cor->ctx);
}
void launch_coroutine(coroutine_t *cor) {
cor->stat = ACTIVE;
cor->entry(cor->arg);
cor->stat = FINISHED;
assert (active_context == &cor->ctx);
switch_to_scheduler();
}
void function_A(void *arg) {
printf("A fn: 1\n");
switch_to_scheduler();
printf("A fn: 2\n");
}
void function_B(void *arg) {
printf("B fn: 1\n");
switch_to_scheduler();
printf("B fn: 2\n");
switch_to_scheduler();
printf("B fn: 3\n");
}
coroutine_t *create_coroutine(entrypoint_t fn, void *arg) {
coroutine_t *cor = (coroutine_t *)malloc(sizeof(coroutine_t));
for (int i=0; i<31; ++i)
cor->ctx.regs[i] = 0;
cor->ctx.regs[REG_SP] = (uint32_t)(&cor->stack[16384]);
cor->ctx.regs[REG_S0] = (uint32_t)cor;
cor->entry = fn;
cor->arg = arg;
cor->stat = START;
cor->ctx.pc = (uint32_t)coroutine_entry;
return cor;
}
void free_coroutine(coroutine_t *cor) {
free(cor);
}
int main() {
coroutine_t *A_cor = create_coroutine(function_A, 0);
coroutine_t *B_cor = create_coroutine(function_B, 0);
_Bool done = 0;
while (!done) {
done = 1;
if (A_cor->stat != FINISHED) {
switch_to_coroutine(A_cor);
done = 0;
}
if (B_cor->stat != FINISHED) {
switch_to_coroutine(B_cor);
done = 0;
}
}
free_coroutine(A_cor);
free_coroutine(B_cor);
return 0;
}
================================================
FILE: sw/simple-sensor/Makefile
================================================
OBJECTS = main.o irq.o bootstrap.o
CFLAGS = -march=rv32i -mabi=ilp32
LDFLAGS = -nostartfiles -Wl,--no-relax
include ../Makefile.common
================================================
FILE: sw/simple-sensor/bootstrap.S
================================================
.globl _start
.globl main
.globl level_1_interrupt_handler
.equ SYSCALL_ADDR, 0x02010000
.equ PLIC_ENABLED_IRQ_ADDR, 0x40002000
.macro SYS_EXIT, exit_code
li a7, 93
li a0, \exit_code
li t0, SYSCALL_ADDR
csrr a6, mhartid
sw a6, 0(t0)
.endm
_start:
la t0, level_0_interrupt_handler
csrw mtvec, t0
li t1, 0x888
csrw mie, t1
csrsi mstatus, 8
li t0, PLIC_ENABLED_IRQ_ADDR
li t1, -1
sw t1, 0(t0)
sw t1, 4(t0)
jal main
# call exit (SYS_EXIT=93) with exit code 0 (argument in a0)
SYS_EXIT 0
/*
* Interrupt handler for non-nested interrupts. Only selected registers are stored/re-stored, i.e. those not preserved on function calls.
*/
#define STORE sw
#define LOAD lw
#define REGBYTES 4
level_0_interrupt_handler:
// store execution context on the stack (register content)
addi sp, sp, -REGBYTES * 32
STORE x1, 0x0(sp)
STORE x4, 3 * REGBYTES(sp)
STORE x5, 4 * REGBYTES(sp)
STORE x6, 5 * REGBYTES(sp)
STORE x7, 6 * REGBYTES(sp)
STORE x10, 9 * REGBYTES(sp)
STORE x11, 10 * REGBYTES(sp)
STORE x12, 11 * REGBYTES(sp)
STORE x13, 12 * REGBYTES(sp)
STORE x14, 13 * REGBYTES(sp)
STORE x15, 14 * REGBYTES(sp)
STORE x16, 15 * REGBYTES(sp)
STORE x17, 16 * REGBYTES(sp)
STORE x28, 27 * REGBYTES(sp)
STORE x29, 28 * REGBYTES(sp)
STORE x30, 29 * REGBYTES(sp)
STORE x31, 30 * REGBYTES(sp)
// load interrupt/trap reason and call external C function to handle it
csrr t2, mcause
srli t3, t2, 31
bnez t3, handle_irq
li t0, SYSCALL_ADDR
csrr t1, mhartid
csrr a7, mcause
sw t1, 0(t0)
csrr t0, mepc
addi t0, t0, 4
csrw mepc, t0
sw a0, 9 * REGBYTES(sp)
j done_trap
handle_irq:
mv a0, t2
jal level_1_interrupt_handler
done_trap:
// re-store the saved context
LOAD x1, 0x0(sp)
LOAD x4, 3 * REGBYTES(sp)
LOAD x5, 4 * REGBYTES(sp)
LOAD x6, 5 * REGBYTES(sp)
LOAD x7, 6 * REGBYTES(sp)
LOAD x10, 9 * REGBYTES(sp)
LOAD x11, 10 * REGBYTES(sp)
LOAD x12, 11 * REGBYTES(sp)
LOAD x13, 12 * REGBYTES(sp)
LOAD x14, 13 * REGBYTES(sp)
LOAD x15, 14 * REGBYTES(sp)
LOAD x16, 15 * REGBYTES(sp)
LOAD x17, 16 * REGBYTES(sp)
LOAD x28, 27 * REGBYTES(sp)
LOAD x29, 28 * REGBYTES(sp)
LOAD x30, 29 * REGBYTES(sp)
LOAD x31, 30 * REGBYTES(sp)
addi sp, sp, REGBYTES * 32
mret
================================================
FILE: sw/simple-sensor/irq.c
================================================
#include "irq.h"
#include "assert.h"
#define RISCV_MACHINE_SOFTWARE_INTERRUPT 3
#define RISCV_MACHINE_TIMER_INTERRUPT 7
#define RISCV_MACHINE_EXTERNAL_INTERRUPT 11
#define PLIC_BASE 0x40000000
#define IRQ_TABLE_NUM_ENTRIES 64
static volatile uint32_t * const PLIC_INTERRUPT_ENABLE_START = (uint32_t * const)(PLIC_BASE + 0x2000);
static volatile uint32_t * const PLIC_CLAIM_AND_RESPONSE_REGISTER = (uint32_t * const)(PLIC_BASE + 0x200004);
static void irq_empty_handler() {}
static irq_handler_t irq_handler_table[IRQ_TABLE_NUM_ENTRIES] = { [ 0 ... IRQ_TABLE_NUM_ENTRIES-1 ] = irq_empty_handler };
#define CLINT_BASE 0x2000000
volatile uint64_t* mtime = (uint64_t*)(CLINT_BASE + 0xbff8);
volatile uint64_t* mtimecmp = (uint64_t*)(CLINT_BASE + 0x4000);
static irq_handler_t timer_irq_handler = 0;
void level_1_interrupt_handler(uint32_t cause) {
switch (cause & 0xf) {
case RISCV_MACHINE_EXTERNAL_INTERRUPT: {
asm volatile ("csrc mip, %0" : : "r" (0x800));
uint32_t irq_id = *PLIC_CLAIM_AND_RESPONSE_REGISTER;
irq_handler_table[irq_id]();
*PLIC_CLAIM_AND_RESPONSE_REGISTER = 1;
return;
}
case RISCV_MACHINE_TIMER_INTERRUPT: {
// Note: the pending timer interrupt bit will be automatically cleared when writing to the *mtimecmp* register of this hart
if (timer_irq_handler) {
// let the user registered handler clear the timer interrupt bit
timer_irq_handler();
} else {
// reset the *mtimecmp* register to zero to clear the pending bit
*mtimecmp = 0;
}
return;
}
}
assert (0 && "unsupported cause");
}
void register_interrupt_handler(uint32_t irq_id, irq_handler_t fn) {
assert (irq_id < IRQ_TABLE_NUM_ENTRIES);
// enable interrupt
volatile uint32_t* const reg = (PLIC_INTERRUPT_ENABLE_START + irq_id/32);
*reg |= 1 << (irq_id%32);
// set a prio different to zero (which means do-not-interrupt)
*((uint32_t*) (PLIC_BASE + irq_id*sizeof(uint32_t))) = 1;
irq_handler_table[irq_id] = fn;
}
void register_timer_interrupt_handler(irq_handler_t fn) {
timer_irq_handler = fn;
}
================================================
FILE: sw/simple-sensor/irq.h
================================================
#ifndef __RISCV_IRQ_H__
#define __RISCV_IRQ_H__
#include "stdint.h"
typedef void (*irq_handler_t)(void);
void register_interrupt_handler(uint32_t irq_id, irq_handler_t fn);
void register_timer_interrupt_handler(irq_handler_t fn);
extern volatile uint64_t* mtime;
extern volatile uint64_t* mtimecmp;
#endif
================================================
FILE: sw/simple-sensor/main.c
================================================
#include <stdint.h>
#include "irq.h"
static volatile char * const TERMINAL_ADDR = (char * const)0x20000000;
static volatile char * const SENSOR_INPUT_ADDR = (char * const)0x50000000;
static volatile uint32_t * const SENSOR_SCALER_REG_ADDR = (uint32_t * const)0x50000080;
static volatile uint32_t * const SENSOR_FILTER_REG_ADDR = (uint32_t * const)0x50000084;
volatile _Bool has_sensor_data = 0;
void sensor_irq_handler() {
has_sensor_data = 1;
}
void dump_sensor_data() {
while (!has_sensor_data) {
asm volatile ("wfi");
}
has_sensor_data = 0;
for (int i=0; i<64; ++i) {
*TERMINAL_ADDR = *(SENSOR_INPUT_ADDR + i) % 92 + 32;
}
*TERMINAL_ADDR = '\n';
}
int main() {
register_interrupt_handler(2, sensor_irq_handler);
*SENSOR_SCALER_REG_ADDR = 5;
*SENSOR_FILTER_REG_ADDR = 2;
for (int i=0; i<3; ++i)
dump_sensor_data();
return 0;
}
================================================
FILE: sw/sys-read/Makefile
================================================
OBJECTS = main.o
CFLAGS = -march=rv32ima -mabi=ilp32
include ../Makefile.common
================================================
FILE: sw/sys-read/main.c
================================================
#include "stdio.h"
int main(int argc, char **argv) {
printf("Enter a number: ");
int c,n = 0;
while (!scanf("%d", &n)) {
printf("Error: unable to parse number\n");
while((c = getchar()) != '\n' && c != EOF);
printf("Enter a number: ");
}
printf("Success, you entered %i\n", n);
return 0;
}
================================================
FILE: sw/sys-read/test-ignore
================================================
================================================
FILE: sw/test.sh
================================================
#!/bin/sh
export SYSTEMC_DISABLE_COPYRIGHT_MESSAGE=1
handle_exit() {
[ $# -eq 1 ] || exit 1
if [ "${1}" -eq 0 ]; then
printf "OK.\n"
else
printf "FAIL.\n"
exit 1
fi
}
for test in *; do
[ -e "${test}/test-ignore" -o -f "${test}" ] && continue
name=${test##*/}
printf "Building sw '%s': " "${name}"
make -C "${test}" >/dev/null
handle_exit $?
printf "Running sw '%s': " "${name}"
make -C "${test}" sim >/dev/null
handle_exit $?
done
================================================
FILE: vp/.gitignore
================================================
build
================================================
FILE: vp/CMakeLists.txt
================================================
cmake_minimum_required(VERSION 3.18)
project(riscv-vp
VERSION 1.2.2
)
option(USE_SYSTEM_SYSTEMC "use systemc version provided by the system" OFF)
if(NOT CMAKE_BUILD_TYPE)
set(CMAKE_BUILD_TYPE Debug)
endif()
set(CMAKE_CXX_STANDARD 17)
set(CMAKE_CXX_FLAGS "-Wall -Wextra -Wno-unused-parameter -Wpedantic")
set(CMAKE_CXX_FLAGS_DEBUG "-g3") #"-fsanitize=address -fno-omit-frame-pointer"
set(CMAKE_CXX_FLAGS_RELEASE "-O3")
# Allows running tests without invoking `make install` first.
set(CMAKE_RUNTIME_OUTPUT_DIRECTORY "${CMAKE_BINARY_DIR}/bin")
set(CMAKE_INSTALL_PREFIX ${CMAKE_BINARY_DIR})
include(cmake/AddGitSubmodule.cmake)
find_package( Boost REQUIRED COMPONENTS iostreams program_options log)
if(USE_SYSTEM_SYSTEMC)
find_library(SystemC libsystemc.a)
endif()
subdirs(src)
enable_testing()
list(APPEND CMAKE_CTEST_ARGUMENTS "--verbose")
add_test(NAME libgdb
COMMAND ./test.sh
WORKING_DIRECTORY "${CMAKE_SOURCE_DIR}/tests/libgdb")
add_test(NAME gdb
COMMAND ./test.sh
WORKING_DIRECTORY "${CMAKE_SOURCE_DIR}/tests/gdb")
add_test(NAME integration
COMMAND ./test.sh
WORKING_DIRECTORY "${CMAKE_SOURCE_DIR}/tests/integration")
add_test(NAME sw
COMMAND ./test.sh
WORKING_DIRECTORY "${CMAKE_SOURCE_DIR}/../sw")
set_tests_properties(gdb integration sw PROPERTIES ENVIRONMENT
PATH=$ENV{PATH}:${CMAKE_RUNTIME_OUTPUT_DIRECTORY})
set_tests_properties(libgdb PROPERTIES ENVIRONMENT
RISCV_VP_BASE=${CMAKE_CURRENT_SOURCE_DIR}/..)
================================================
FILE: vp/cmake/AddGitSubmodule.cmake
================================================
#thanks @ https://gist.github.com/scivision/bb1d47a9529e153617414e91ff5390af
cmake_minimum_required(VERSION 3.16)
function(add_git_submodule dir)
# add a Git submodule directory to CMake, assuming the
# Git submodule directory is a CMake project.
#
# Usage: in CMakeLists.txt
#
# include(AddGitSubmodule.cmake)
# add_git_submodule(mysubmod_dir)
find_package(Git REQUIRED)
if(NOT EXISTS ${dir})
set(dir ${CMAKE_CURRENT_SOURCE_DIR}/${dir})
endif()
if(NOT EXISTS "${dir}/CMakeLists.txt")
message("checking out submodule ${dir}")
execute_process(COMMAND ${GIT_EXECUTABLE} submodule update --init --recursive -- ${abs_dir}
WORKING_DIRECTORY ${PROJECT_SOURCE_DIR}
#COMMAND_ERROR_IS_FATAL # cmake 3.19+
#ANY # cmake 3.19+
)
endif()
add_subdirectory(${dir})
endfunction(add_git_submodule)
================================================
FILE: vp/src/CMakeLists.txt
================================================
include_directories(.)
subdirs(vendor)
subdirs(core)
subdirs(platform)
================================================
FILE: vp/src/core/CMakeLists.txt
================================================
subdirs(common)
subdirs(rv32)
subdirs(rv64)
================================================
FILE: vp/src/core/common/CMakeLists.txt
================================================
file(GLOB_RECURSE HEADERS ${CMAKE_CURRENT_SOURCE_DIR}/*.h)
add_library(core-common
timer.cpp
real_clint.cpp
instr.cpp
debug_memory.cpp
rawmode.cpp
${HEADERS})
target_include_directories(core-common PUBLIC ${CMAKE_CURRENT_SOURCE_DIR})
target_link_libraries(core-common PRIVATE pthread systemc)
add_subdirectory(gdb-mc)
================================================
FILE: vp/src/core/common/bus_lock_if.h
================================================
#pragma once
struct bus_lock_if {
virtual ~bus_lock_if() {}
virtual void lock(unsigned hart_id) = 0;
virtual void unlock(unsigned hart_id) = 0;
virtual bool is_locked() = 0; // by any hart
virtual bool is_locked(unsigned hart_id) = 0;
virtual void wait_until_unlocked() = 0;
inline void wait_for_access_rights(unsigned hart_id) {
if (is_locked() && !is_locked(hart_id))
wait_until_unlocked();
}
};
================================================
FILE: vp/src/core/common/clint.h
================================================
#ifndef RISCV_ISA_CLINT_H
#define RISCV_ISA_CLINT_H
#include "clint_if.h"
#include "irq_if.h"
#include <tlm_utils/simple_target_socket.h>
#include <systemc>
#include "util/memory_map.h"
template <unsigned NumberOfCores>
struct CLINT : public clint_if, public sc_core::sc_module {
//
// core local interrupt controller (provides local timer interrupts with
// memory mapped configuration)
//
// send out interrupt if: *mtime >= mtimecmp* and *mtimecmp != 0*
//
// *mtime* is a read-only 64 bit timer register shared by all CPUs (accessed
// by MMIO and also mapped into the CSR address space of each CPU)
//
// for every CPU a *mtimecmp* register (read/write 64 bit) is available
//
//
// Note: the software is responsible to ensure that no overflow occurs when
// writing *mtimecmp* (see RISC-V privileged ISA spec.):
//
// # New comparand is in a1:a0.
// li t0, -1
// sw t0, mtimecmp # No smaller than old value.
// sw a1, mtimecmp+4 # No smaller than new value.
// sw a0, mtimecmp # New value.
//
static_assert(NumberOfCores < 4096, "out of bound"); // stay within the allocated address range
static constexpr uint64_t scaler = 1000000; // scale from PS resolution (default in SystemC) to US
// resolution (apparently required by FreeRTOS)
tlm_utils::simple_target_socket<CLINT> tsock;
sc_core::sc_time clock_cycle = sc_core::sc_time(10, sc_core::SC_NS);
sc_core::sc_event irq_event;
RegisterRange regs_mtime{0xBFF8, 8};
IntegerView<uint64_t> mtime{regs_mtime};
RegisterRange regs_mtimecmp{0x4000, 8 * NumberOfCores};
ArrayView<uint64_t> mtimecmp{regs_mtimecmp};
RegisterRange regs_msip{0x0, 4 * NumberOfCores};
ArrayView<uint32_t> msip{regs_msip};
std::vector<RegisterRange *> register_ranges{®s_mtime, ®s_mtimecmp, ®s_msip};
std::array<clint_interrupt_target *, NumberOfCores> target_harts{};
SC_HAS_PROCESS(CLINT);
CLINT(sc_core::sc_module_name) {
tsock.register_b_transport(this, &CLINT::transport);
regs_mtimecmp.alignment = 4;
regs_msip.alignment = 4;
regs_mtime.alignment = 4;
regs_mtime.pre_read_callback = std::bind(&CLINT::pre_read_mtime, this, std::placeholders::_1);
regs_mtimecmp.post_write_callback = std::bind(&CLINT::post_write_mtimecmp, this, std::placeholders::_1);
regs_msip.post_write_callback = std::bind(&CLINT::post_write_msip, this, std::placeholders::_1);
SC_THREAD(run);
}
uint64_t update_and_get_mtime() override {
auto now = sc_core::sc_time_stamp().value() / scaler;
if (now > mtime)
mtime = now; // do not update backward in time (e.g. due to local quantums in tlm transaction processing)
return mtime;
}
void run() {
while (true) {
sc_core::wait(irq_event);
update_and_get_mtime();
for (unsigned i = 0; i < NumberOfCores; ++i) {
auto cmp = mtimecmp[i];
// std::cout << "[vp::clint] process mtimecmp[" << i << "]=" << cmp << ", mtime=" << mtime << std::endl;
if (cmp > 0 && mtime >= cmp) {
// std::cout << "[vp::clint] set timer interrupt for core " << i << std::endl;
target_harts[i]->trigger_timer_interrupt(true);
} else {
// std::cout << "[vp::clint] unset timer interrupt for core " << i << std::endl;
target_harts[i]->trigger_timer_interrupt(false);
if (cmp > 0 && cmp < UINT64_MAX) {
auto time = sc_core::sc_time::from_value(mtime * scaler);
auto goal = sc_core::sc_time::from_value(cmp * scaler);
// std::cout << "[vp::clint] time=" << time << std::endl;
// std::cout << "[vp::clint] goal=" << goal << std::endl;
// std::cout << "[vp::clint] goal-time=delay=" << goal-time << std::endl;
irq_event.notify(goal - time);
}
}
}
}
}
bool pre_read_mtime(RegisterRange::ReadInfo t) {
sc_core::sc_time now = sc_core::sc_time_stamp() + t.delay;
mtime.write(now.value() / scaler);
return true;
}
void post_write_mtimecmp(RegisterRange::WriteInfo t) {
// std::cout << "[vp::clint] write mtimecmp[addr=" << t.addr << "]=" << mtimecmp[t.addr / 8] << ", mtime=" <<
// mtime << std::endl;
irq_event.notify(t.delay);
}
void post_write_msip(RegisterRange::WriteInfo t) {
assert(t.addr % 4 == 0);
unsigned idx = t.addr / 4;
msip[idx] &= 0x1;
target_harts[idx]->trigger_software_interrupt(msip[idx] != 0);
}
void transport(tlm::tlm_generic_payload &trans, sc_core::sc_time &delay) {
delay += 2 * clock_cycle;
vp::mm::route("CLINT", register_ranges, trans, delay);
}
};
#endif // RISCV_ISA_CLINT_H
================================================
FILE: vp/src/core/common/clint_if.h
================================================
#pragma once
#include <stdint.h>
struct clint_if {
virtual ~clint_if() {}
virtual uint64_t update_and_get_mtime() = 0;
};
================================================
FILE: vp/src/core/common/core_defs.h
================================================
#pragma once
enum Architecture {
RV32 = 1,
RV64 = 2,
RV128 = 3,
};
enum class CoreExecStatus {
Runnable,
HitBreakpoint,
Terminated,
};
constexpr unsigned SATP_MODE_BARE = 0;
constexpr unsigned SATP_MODE_SV32 = 1;
constexpr unsigned SATP_MODE_SV39 = 8;
constexpr unsigned SATP_MODE_SV48 = 9;
constexpr unsigned SATP_MODE_SV57 = 10;
constexpr unsigned SATP_MODE_SV64 = 11;
================================================
FILE: vp/src/core/common/debug.h
================================================
#ifndef RISCV_DEBUG
#define RISCV_DEBUG
#include <stdint.h>
#include <unordered_set>
#include <vector>
#include "core_defs.h"
struct debug_target_if {
virtual ~debug_target_if() {}
virtual void enable_debug(void) = 0;
virtual CoreExecStatus get_status(void) = 0;
virtual void set_status(CoreExecStatus) = 0;
virtual void block_on_wfi(bool) = 0;
virtual void insert_breakpoint(uint64_t) = 0;
virtual void remove_breakpoint(uint64_t) = 0;
virtual Architecture get_architecture(void) = 0;
virtual uint64_t get_hart_id(void) = 0;
virtual uint64_t get_progam_counter(void) = 0;
virtual std::vector<uint64_t> get_registers(void) = 0;
virtual uint64_t read_register(unsigned) = 0;
virtual void run(void) = 0;
virtual void run_step(void) = 0;
};
#endif
================================================
FILE: vp/src/core/common/debug_memory.cpp
================================================
#include "debug_memory.h"
#include <assert.h>
#include <stdio.h>
#include <stdint.h>
#include <stdlib.h>
#include <errno.h>
#include <arpa/inet.h>
#include <byteswap.h>
#include <netinet/in.h>
#include <netinet/ip.h>
#include <sys/socket.h>
#include <sys/types.h>
#include <cassert>
#include <cstdint>
#include <cstdio>
#include <cstdlib>
#include <iomanip>
#include <iostream>
#include <sstream>
#include <string>
#include <boost/algorithm/string.hpp>
#include <boost/algorithm/string/predicate.hpp>
#include <boost/lexical_cast.hpp>
unsigned DebugMemoryInterface::_do_dbg_transaction(tlm::tlm_command cmd, uint64_t addr, uint8_t *data,
unsigned num_bytes) {
tlm::tlm_generic_payload trans;
trans.set_command(cmd);
trans.set_address(addr);
trans.set_data_ptr(data);
trans.set_data_length(num_bytes);
trans.set_response_status(tlm::TLM_OK_RESPONSE);
unsigned nbytes = isock->transport_dbg(trans);
if (trans.is_response_error())
throw std::runtime_error("debug transaction failed");
return nbytes;
}
std::string DebugMemoryInterface::read_memory(uint64_t start, unsigned nbytes) {
std::vector<uint8_t> buf(nbytes); // NOTE: every element is zero-initialized by default
unsigned nbytes_read = _do_dbg_transaction(tlm::TLM_READ_COMMAND, start, buf.data(), buf.size());
assert(nbytes_read == nbytes && "not all bytes read");
std::stringstream stream;
stream << std::setfill('0') << std::hex;
for (uint8_t byte : buf) {
stream << std::setw(2) << (unsigned)byte;
}
return stream.str();
}
void DebugMemoryInterface::write_memory(uint64_t start, unsigned nbytes, const std::string &data) {
unsigned i, j;
std::vector<uint8_t> buf(data.length() / 2);
assert(data.length() % 2 == 0);
assert(buf.size() == nbytes);
for (j = 0, i = 0; i + 1 < nbytes; j++, i += 2) {
long num;
char hex[3];
hex[0] = data.at(i);
hex[1] = data.at(i+1);
hex[2] = '\0';
errno = 0;
num = strtol(hex, NULL, 16);
if (num == 0 && errno != 0)
throw std::system_error(errno, std::generic_category());
assert(num >= 0 && num <= UINT8_MAX);
buf.at(j) = (uint8_t)num;
}
unsigned nbytes_write = _do_dbg_transaction(tlm::TLM_WRITE_COMMAND, start, buf.data(), buf.size());
assert(nbytes_write == nbytes && "not all data written");
}
================================================
FILE: vp/src/core/common/debug_memory.h
================================================
#ifndef RISCV_ISA_DEBUG_MEMORY_H
#define RISCV_ISA_DEBUG_MEMORY_H
#include <string>
#include <type_traits>
#include <tlm_utils/simple_initiator_socket.h>
#include <systemc>
#include "core_defs.h"
#include "trap.h"
struct DebugMemoryInterface : public sc_core::sc_module {
tlm_utils::simple_initiator_socket<DebugMemoryInterface> isock;
DebugMemoryInterface(sc_core::sc_module_name) {}
unsigned _do_dbg_transaction(tlm::tlm_command cmd, uint64_t addr, uint8_t *data, unsigned num_bytes);
std::string read_memory(uint64_t start, unsigned nbytes);
void write_memory(uint64_t start, unsigned nbytes, const std::string &data);
};
#endif // RISCV_ISA_GDB_STUB_H
================================================
FILE: vp/src/core/common/dmi.h
================================================
#pragma once
#include <stdint.h>
class MemoryDMI {
uint8_t *mem;
uint64_t start;
uint64_t size;
uint64_t end;
MemoryDMI(uint8_t *mem, uint64_t start, uint64_t size) : mem(mem), start(start), size(size), end(start + size) {}
public:
static MemoryDMI create_start_end_mapping(uint8_t *mem, uint64_t start, uint64_t end) {
assert(end > start);
return create_start_size_mapping(mem, start, end - start);
}
static MemoryDMI create_start_size_mapping(uint8_t *mem, uint64_t start, uint64_t size) {
assert(start + size > start);
return MemoryDMI(mem, start, size);
}
uint8_t *get_raw_mem_ptr() {
return mem;
}
template <typename T>
T *get_mem_ptr_to_global_addr(uint64_t addr) {
assert(contains(addr));
assert((addr + sizeof(T)) <= end);
// assert ((addr % sizeof(T)) == 0 && "unaligned access"); //NOTE: due to compressed instructions, fetching
// can be unaligned
return reinterpret_cast<T *>(mem + (addr - start));
}
template <typename T>
T load(uint64_t addr) {
static_assert(std::is_integral<T>::value, "integer type required");
T ans;
T *src = get_mem_ptr_to_global_addr<T>(addr);
// use memcpy to avoid problems with unaligned loads into standard C++ data types
// see: https://blog.quarkslab.com/unaligned-accesses-in-cc-what-why-and-solutions-to-do-it-properly.html
memcpy(&ans, src, sizeof(T));
return ans;
}
template <typename T>
void store(uint64_t addr, T value) {
static_assert(std::is_integral<T>::value, "integer type required");
T *dst = get_mem_ptr_to_global_addr<T>(addr);
memcpy(dst, &value, sizeof(value));
}
uint64_t get_start() {
return start;
}
uint64_t get_end() {
return start + size;
}
uint64_t get_size() {
return size;
}
bool contains(uint64_t addr) {
return addr >= start && addr < end;
}
};
================================================
FILE: vp/src/core/common/elf_loader.h
================================================
#pragma once
#include <boost/iostreams/device/mapped_file.hpp>
#include <exception>
#include <cstdint>
#include <vector>
#include "load_if.h"
template <typename T>
struct GenericElfLoader {
typedef typename T::addr_t addr_t;
typedef typename T::Elf_Ehdr Elf_Ehdr;
typedef typename T::Elf_Phdr Elf_Phdr;
typedef typename T::Elf_Shdr Elf_Shdr;
typedef typename T::Elf_Sym Elf_Sym;
static_assert(sizeof(addr_t) == sizeof(Elf_Ehdr::e_entry), "architecture mismatch");
const char *filename;
boost::iostreams::mapped_file_source elf;
const Elf_Ehdr *hdr;
struct load_executable_exception : public std::exception {
const char * what () const throw () {
return "Tried loading invalid elf layout";
}
};
GenericElfLoader(const char *filename) : filename(filename), elf(filename) {
assert(elf.is_open() && "file not open");
hdr = reinterpret_cast<const Elf_Ehdr *>(elf.data());
}
std::vector<const Elf_Phdr *> get_load_sections() {
std::vector<const Elf_Phdr *> sections;
for (int i = 0; i < hdr->e_phnum; ++i) {
const Elf_Phdr *p =
reinterpret_cast<const typename T::Elf_Phdr *>(elf.data() + hdr->e_phoff + hdr->e_phentsize * i);
if (p->p_type != T::PT_LOAD)
continue;
if ((p->p_filesz == 0) && (p->p_memsz == 0))
continue;
//If p_memsz is greater than p_filesz, the extra bytes are NOBITS.
// -> still, the memory needs to be zero initialized in this case!
// if (p->p_memsz > p->p_filesz)
// continue;
sections.push_back(p);
}
return sections;
}
std::ostream& print_phdr(std::ostream& os, const Elf_Phdr& h, unsigned tabs = 0)
{
std::string tab(tabs, '\t');
os << tab << "p_type " << h.p_type << std::endl;
os << tab << "p_offset "<< h.p_offset << std::endl;
os << tab << "p_vaddr " << h.p_vaddr << std::endl;
os << tab << "p_paddr " << h.p_paddr << std::endl;
os << tab << "p_filesz "<< h.p_filesz << std::endl;
os << tab << "p_memsz " << h.p_memsz << std::endl;
os << tab << "p_flags " << h.p_flags << std::endl;
os << tab << "p_align " << h.p_align << std::endl;
return os;
}
void load_executable_image(load_if &load_if, addr_t size, addr_t offset, bool use_vaddr = true) {
for (auto p : get_load_sections()) {
auto addr = p->p_paddr;
if (use_vaddr)
addr = p->p_vaddr;
// If the modeled virtual platform separates Flash and DRAM
// (like the hifive-vp does) we call load_executable_image
// once for each memory segment (i.e. once for the Flash and
// once for the DRAM). As such, we must skip all ELF regions
// which are not covered by the passed memory segment.
if (!(addr >= offset && addr < (offset + size)))
continue;
if (addr < offset) {
std::cerr << "[elf_loader] ";
std::cerr << "Offset overlaps into section:" << std::endl;
std::cerr << "\t0x" << std::hex << +addr << " < " << +offset << std::endl;
print_phdr(std::cerr, *p, 2);
throw load_executable_exception();
}
if (addr + p->p_memsz >= offset + size) {
std::cerr << "[elf_loader] ";
std::cerr << "Section does not fit in target memory" << std::endl;
std::cerr << "\t0x" << std::hex << +addr << " + size 0x" << +p->p_memsz;
std::cerr << " would overflow offset 0x" << +offset << " + size 0x" << +size << std::endl;
print_phdr(std::cerr, *p, 2);
throw load_executable_exception();
}
auto idx = addr - offset;
const char *src = elf.data() + p->p_offset;
auto to_copy = p->p_filesz;
load_if.load_data(src, idx, to_copy);
assert (p->p_memsz >= p->p_filesz);
idx = idx + p->p_filesz;
to_copy = p->p_memsz - p->p_filesz;
load_if.load_zero(idx, to_copy);
}
}
addr_t get_memory_end() {
const Elf_Phdr *last =
reinterpret_cast<const Elf_Phdr *>(elf.data() + hdr->e_phoff + hdr->e_phentsize * (hdr->e_phnum - 1));
return last->p_vaddr + last->p_memsz;
}
addr_t get_heap_addr() {
// return first 8 byte aligned address after the memory image
auto s = get_memory_end();
return s + s % 8;
}
addr_t get_entrypoint() {
return hdr->e_entry;
}
const char *get_section_string_table() {
assert(hdr->e_shoff != 0 && "string table section not available");
const Elf_Shdr *s =
reinterpret_cast<const Elf_Shdr *>(elf.data() + hdr->e_shoff + hdr->e_shentsize * hdr->e_shstrndx);
const char *start = elf.data() + s->sh_offset;
return start;
}
const char *get_symbol_string_table() {
auto s = get_section(".strtab");
return elf.data() + s->sh_offset;
}
const Elf_Sym *get_symbol(const char *symbol_name) {
const Elf_Shdr *s = get_section(".symtab");
const char *strings = get_symbol_string_table();
assert(s->sh_size % sizeof(Elf_Sym) == 0);
auto num_entries = s->sh_size / sizeof(typename T::Elf_Sym);
for (unsigned i = 0; i < num_entries; ++i) {
const Elf_Sym *p = reinterpret_cast<const Elf_Sym *>(elf.data() + s->sh_offset + i * sizeof(Elf_Sym));
// std::cout << "check symbol: " << strings + p->st_name << std::endl;
if (!strcmp(strings + p->st_name, symbol_name)) {
return p;
}
}
throw std::runtime_error("unable to find symbol in the symbol table " + std::string(symbol_name));
}
addr_t get_begin_signature_address() {
auto p = get_symbol("begin_signature");
return p->st_value;
}
addr_t get_end_signature_address() {
auto p = get_symbol("end_signature");
return p->st_value;
}
addr_t get_to_host_address() {
auto p = get_symbol("tohost");
return p->st_value;
}
std::vector<const Elf_Shdr *> get_sections(void) {
if (hdr->e_shoff == 0) {
throw std::runtime_error("unable to find section address, section table not available");
}
std::vector<const Elf_Shdr *> sections;
for (unsigned i = 0; i < hdr->e_shnum; ++i) {
const Elf_Shdr *s = reinterpret_cast<const Elf_Shdr *>(elf.data() + hdr->e_shoff + hdr->e_shentsize * i);
sections.push_back(s);
}
return sections;
}
const Elf_Shdr *get_section(const char *section_name) {
const char *strings = get_section_string_table();
for (auto s : get_sections()) {
if (!strcmp(strings + s->sh_name, section_name)) {
return s;
}
}
throw std::runtime_error("unable to find section address, section seems not available: " +
std::string(section_name));
}
};
================================================
FILE: vp/src/core/common/fp.h
================================================
#pragma once
#include <softfloat/softfloat.hpp>
// floating-point rounding modes
constexpr unsigned FRM_RNE = 0b000; // Round to Nearest, ties to Even
constexpr unsigned FRM_RTZ = 0b001; // Round towards Zero
constexpr unsigned FRM_RDN = 0b010; // Round Down (towards -inf)
constexpr unsigned FRM_RUP = 0b011; // Round Down (towards +inf)
constexpr unsigned FRM_RMM = 0b100; // Round to Nearest, ties to Max Magnitude
constexpr unsigned FRM_DYN =
0b111; // In instruction’s rm field, selects dynamic rounding mode; In Rounding Mode register, Invalid
// NaN values
constexpr uint32_t defaultNaNF32UI = 0x7fc00000;
constexpr uint64_t defaultNaNF64UI = 0x7FF8000000000000;
constexpr float32_t f32_defaultNaN = {defaultNaNF32UI};
constexpr float64_t f64_defaultNaN = {defaultNaNF64UI};
constexpr uint32_t F32_SIGN_BIT = 1 << 31;
constexpr uint64_t F64_SIGN_BIT = 1ul << 63;
inline bool f32_isNegative(float32_t x) {
return x.v & F32_SIGN_BIT;
}
inline bool f64_isNegative(float64_t x) {
return x.v & F64_SIGN_BIT;
}
inline float32_t f32_neg(float32_t x) {
return float32_t{x.v ^ F32_SIGN_BIT};
}
inline float64_t f64_neg(float64_t x) {
return float64_t{x.v ^ F64_SIGN_BIT};
}
inline bool f32_isNaN(float32_t x) {
// f32 NaN:
// - sign bit can be 0 or 1
// - all exponent bits set
// - at least one fraction bit set
return ((~x.v & 0x7F800000) == 0) && (x.v & 0x007FFFFF);
}
inline bool f64_isNaN(float64_t x) {
// similar to f32 NaN
return ((~x.v & 0x7FF0000000000000) == 0) && (x.v & 0x000FFFFFFFFFFFFF);
}
struct FpRegs {
private:
std::array<float64_t, 32> regs;
bool is_boxed_f32(float64_t x) {
return (x.v >> 32) == (uint32_t)-1;
}
float32_t unbox_f32(float64_t x) {
return float32_t{(uint32_t)x.v};
}
float64_t box_f32(float32_t x) {
return float64_t{(uint64_t)x.v | 0xFFFFFFFF00000000};
}
public:
void write(unsigned idx, float32_t x) {
write(idx, box_f32(x));
}
void write(unsigned idx, float64_t x) {
regs[idx] = x;
}
uint32_t u32(unsigned idx) {
// access raw data, e.g. to store to memory
return regs[idx].v;
}
float32_t f32(unsigned idx) {
if (is_boxed_f32(regs[idx]))
return unbox_f32(regs[idx]);
else
return f32_defaultNaN;
}
float64_t f64(unsigned idx) {
return regs[idx];
}
};
================================================
FILE: vp/src/core/common/gdb-mc/CMakeLists.txt
================================================
add_subdirectory(libgdb)
add_library(gdb-mc
gdb_server.cpp
gdb_runner.cpp
register_format.cpp
handler.cpp)
target_link_libraries(gdb-mc gdb core-common systemc)
================================================
FILE: vp/src/core/common/gdb-mc/gdb_runner.cpp
================================================
#include "gdb_runner.h"
GDBServerRunner::GDBServerRunner(sc_core::sc_module_name name, GDBServer *server, debug_target_if *hart) {
(void)name;
this->hart = hart;
this->server = server;
this->stop_event = server->get_stop_event(hart);
server->set_run_event(hart, &this->run_event);
hart->enable_debug();
SC_THREAD(run);
}
void GDBServerRunner::run(void) {
for (;;) {
sc_core::wait(run_event);
if (server->single_run) {
hart->run_step();
if (hart->get_status() == CoreExecStatus::Runnable)
hart->set_status(CoreExecStatus::HitBreakpoint);
} else {
hart->run();
}
stop_event->notify();
if (hart->get_status() == CoreExecStatus::Terminated)
break;
}
}
================================================
FILE: vp/src/core/common/gdb-mc/gdb_runner.h
================================================
#ifndef RISCV_GDB_RUNNER
#define RISCV_GDB_RUNNER
#include <systemc>
#include "debug.h"
#include "gdb_server.h"
SC_MODULE(GDBServerRunner) {
public:
SC_HAS_PROCESS(GDBServerRunner);
GDBServerRunner(sc_core::sc_module_name, GDBServer *, debug_target_if *);
private:
GDBServer *server;
debug_target_if *hart;
sc_core::sc_event run_event;
sc_core::sc_event *stop_event;
void run(void);
};
#endif
================================================
FILE: vp/src/core/common/gdb-mc/gdb_server.cpp
================================================
#include <err.h>
#include <assert.h>
#include <stdio.h>
#include <string.h>
#include <unistd.h>
#include <stdint.h>
#include <stdlib.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <netinet/tcp.h>
#include <libgdb/parser2.h>
#include <libgdb/response.h>
#include <systemc>
#include "gdb_server.h"
#include "platform/common/async_event.h"
extern std::map<std::string, GDBServer::packet_handler> handlers;
GDBServer::GDBServer(sc_core::sc_module_name name,
std::vector<debug_target_if*> targets,
DebugMemoryInterface *mm,
uint16_t port,
std::vector<mmu_memory_if*> mmus) {
(void)name;
if (targets.size() <= 0)
throw std::invalid_argument("no harts specified");
if (mmus.size() > 0 && mmus.size() != targets.size())
throw std::invalid_argument("invalid amount of MMUs specified");
for (size_t i = 0; i < targets.size(); i++) {
debug_target_if *target = targets.at(i);
harts.push_back(target);
events[target] = std::make_tuple(new sc_core::sc_event, (sc_core::sc_event *)NULL);
if (mmus.size() > 0)
mmu[target] = mmus.at(i);
/* Don't block on WFI, otherwise the run_threads method
* does not work correctly. Allowing blocking WFI would
* likely increase the performance */
target->block_on_wfi(false);
}
memory = mm;
arch = harts.at(0)->get_architecture(); // assuming all harts use the same
prevpkt = NULL;
create_sock(port);
SC_THREAD(run);
thr = std::thread(&GDBServer::serve, this);
thr.detach();
}
sc_core::sc_event *GDBServer::get_stop_event(debug_target_if *hart) {
return std::get<0>(events.at(hart));
}
void GDBServer::set_run_event(debug_target_if *hart, sc_core::sc_event *event) {
std::get<1>(events.at(hart)) = event;
}
void GDBServer::create_sock(uint16_t port) {
struct sockaddr_in addr;
int reuse;
sockfd = socket(AF_INET, SOCK_STREAM, 0);
if (sockfd == -1)
throw std::system_error(errno, std::generic_category());
reuse = 1;
if (setsockopt(sockfd, SOL_TCP, TCP_NODELAY, &reuse, sizeof(reuse)) == -1)
goto err;
if (setsockopt(sockfd, SOL_SOCKET, SO_REUSEPORT, &reuse, sizeof(reuse)) == -1)
goto err;
memset(&addr, 0, sizeof(addr));
addr.sin_family = AF_INET;
addr.sin_addr.s_addr = htonl(INADDR_LOOPBACK);
addr.sin_port = htons(port);
if (bind(sockfd, (struct sockaddr *)&addr, sizeof(addr)) == -1)
goto err;
if (listen(sockfd, 0) == -1)
goto err;
return;
err:
close(sockfd);
throw std::system_error(errno, std::generic_category());
}
std::vector<debug_target_if *> GDBServer::get_threads(int id) {
if (id == GDB_THREAD_ANY)
id = 1; /* pick the first thread */
if (id == GDB_THREAD_ALL)
return harts;
if (id < 1) /* thread ids should start at index 1 */
throw std::out_of_range("Thread id is too small");
else
id--;
std::vector<debug_target_if *> v;
v.push_back(harts.at(id));
return v;
}
uint64_t GDBServer::translate_addr(debug_target_if *hart, uint64_t addr, MemoryAccessType type) {
mmu_memory_if *mmu_if;
try {
mmu_if = mmu.at(hart);
} catch (const std::out_of_range&) {
mmu_if = NULL;
}
if (!mmu_if) {
return addr;
} else {
return mmu_if->v2p(addr, type);
}
}
void GDBServer::exec_thread(thread_func fn, char op) {
int thread;
std::vector<debug_target_if *> threads;
try {
thread = thread_ops.at(op);
} catch (const std::out_of_range&) {
thread = GDB_THREAD_ANY;
}
threads = get_threads(thread);
for (debug_target_if *thread : threads)
fn(thread);
}
std::vector<debug_target_if *> GDBServer::run_threads(std::vector<debug_target_if *> hartsrun, bool single) {
if (hartsrun.empty()) {
return hartsrun;
}
this->single_run = single;
/* invoke all selected harts */
sc_core::sc_event_or_list allharts;
for (debug_target_if *hart : hartsrun) {
sc_core::sc_event *stop_event, *run_event;
std::tie (stop_event, run_event) = this->events.at(hart);
run_event->notify();
allharts |= *stop_event;
}
/* wait until the first hart finishes execution */
sc_core::wait(allharts);
/* ensure that all running harts are stopped */
std::vector<CoreExecStatus> orig_status;
for (debug_target_if *hart : hartsrun) {
CoreExecStatus status = hart->get_status();
orig_status.push_back(status);
if (status != CoreExecStatus::Runnable)
continue;
hart->set_status(CoreExecStatus::HitBreakpoint);
sc_core::sc_event &stopev = *get_stop_event(hart);
sc_core::wait(stopev);
}
/* restore original hart status */
assert(orig_status.size() == hartsrun.size());
for (size_t i = 0; i < hartsrun.size(); i++)
hartsrun[i]->set_status(orig_status[i]);
return hartsrun;
}
void GDBServer::writeall(int fd, char *data, size_t len) {
ssize_t ret, w;
w = 0;
do {
assert(len >= (size_t)w);
ret = write(fd, &data[w], len - (size_t)w);
if (ret < 0)
throw std::system_error(errno, std::generic_category());
w += ret;
} while ((size_t)w < len);
}
void GDBServer::send_packet(int conn, const char *data, gdb_kind_t kind) {
char *serialized;
serialized = gdb_serialize(kind, data);
try {
writeall(conn, serialized, strlen(serialized));
} catch (const std::system_error& e) {
warnx("writeall failed: %s", e.what());
goto ret;
}
/* acknowledgment are only used for GDB packets */
if (kind != GDB_KIND_PACKET)
goto ret;
free(prevpkt);
if (!(prevpkt = strdup(serialized))) {
prevpkt = NULL;
free(serialized);
throw std::system_error(errno, std::generic_category());
}
ret:
free(serialized);
}
void GDBServer::retransmit(int conn) {
if (!prevpkt)
return;
try {
writeall(conn, prevpkt, strlen(prevpkt));
} catch (const std::system_error& e) {
warnx("writeall failed: %s", e.what());
}
/* memory for prevpkt is freed on next successfull
* packet transmit in the send_packet function */
}
void GDBServer::dispatch(int conn) {
FILE *stream;
gdb_packet_t *pkt;
if (!(stream = fdopen(conn, "r")))
throw std::system_error(errno, std::generic_category());
for (;;) {
mtx.lock();
if (!(pkt = gdb_parse_pkt(stream))) {
mtx.unlock();
break;
}
pktq.push(std::make_tuple(conn, pkt));
asyncEvent.notify();
/* further processing is performed in the SystemC run()
* thread which interacts with the ISS objects and
* unlocks the mutex after finishing all operations. */
}
fclose(stream);
}
void GDBServer::serve(void) {
int conn;
for (;;) {
if ((conn = accept(sockfd, NULL, NULL)) == -1) {
warn("accept failed");
continue;
}
dispatch(conn);
close(conn);
free(prevpkt);
prevpkt = NULL;
}
}
void GDBServer::run(void) {
int conn;
gdb_command_t *cmd;
gdb_packet_t *pkt;
packet_handler handler;
for (;;) {
sc_core::wait(asyncEvent);
auto ctx = pktq.front();
std::tie (conn, pkt) = ctx;
switch (pkt->kind) {
case GDB_KIND_NACK:
retransmit(conn);
/* fall through */
case GDB_KIND_ACK:
goto next1;
default:
break;
}
if (!(cmd = gdb_parse_cmd(pkt))) {
send_packet(conn, NULL, GDB_KIND_NACK);
goto next1;
}
send_packet(conn, NULL, GDB_KIND_ACK);
try {
handler = handlers.at(cmd->name);
} catch (const std::out_of_range&) {
// For any command not supported by the stub, an
// empty response (‘$#00’) should be returned.
send_packet(conn, "");
goto next2;
}
(this->*handler)(conn, cmd);
next2:
gdb_free_cmd(cmd);
next1:
gdb_free_packet(pkt);
pktq.pop();
mtx.unlock();
}
}
================================================
FILE: vp/src/core/common/gdb-mc/gdb_server.h
================================================
#ifndef RISCV_GDB_NG
#define RISCV_GDB_NG
#include <stdint.h>
#include <stddef.h>
#include <stdbool.h>
#include <queue>
#include <mutex>
#include <systemc>
#include <thread>
#include <map>
#include <tuple>
#include <functional>
#include <core/common/mmu_mem_if.h>
#include <libgdb/parser2.h>
#include "debug.h"
#include "core_defs.h"
#include "platform/common/async_event.h"
#include "debug_memory.h" // DebugMemoryInterface
SC_MODULE(GDBServer) {
public:
typedef void (GDBServer::*packet_handler)(int, gdb_command_t *);
void haltReason(int, gdb_command_t *);
void getRegisters(int, gdb_command_t *);
void setThread(int, gdb_command_t *);
void killServer(int, gdb_command_t *);
void readMemory(int, gdb_command_t *);
void writeMemory(int, gdb_command_t *);
void readRegister(int, gdb_command_t *);
void qAttached(int, gdb_command_t *);
void qSupported(int, gdb_command_t *);
void threadInfo(int, gdb_command_t *);
void threadInfoEnd(int, gdb_command_t *);
void vCont(int, gdb_command_t *);
void vContSupported(int, gdb_command_t *);
void removeBreakpoint(int, gdb_command_t *);
void setBreakpoint(int, gdb_command_t *);
void isAlive(int, gdb_command_t *);
SC_HAS_PROCESS(GDBServer);
GDBServer(sc_core::sc_module_name,
std::vector<debug_target_if*>,
DebugMemoryInterface*,
uint16_t,
std::vector<mmu_memory_if*> mmus = {});
/* Used by GDBRunner to determine whether run() or run_step()
* should be used when receiving a run event for a debug_target_if.
*
* TODO: Pass this on a per-event basis instead. */
bool single_run = false;
sc_core::sc_event *get_stop_event(debug_target_if *);
void set_run_event(debug_target_if *, sc_core::sc_event *);
private:
typedef std::function<void(debug_target_if *)> thread_func;
typedef std::tuple<int, gdb_packet_t *> ctx;
typedef std::tuple<sc_core::sc_event *, sc_core::sc_event *> hart_event;
DebugMemoryInterface *memory;
AsyncEvent asyncEvent;
Architecture arch;
std::vector<debug_target_if*> harts;
std::thread thr;
char *prevpkt;
std::queue<ctx> pktq;
std::mutex mtx;
int sockfd;
/* operation → thread id */
std::map<char, int> thread_ops;
/* hart → events */
std::map<debug_target_if *, hart_event> events;
/* hart → mmu */
std::map<debug_target_if *, mmu_memory_if *> mmu;
void create_sock(uint16_t);
std::vector<debug_target_if *> get_threads(int);
uint64_t translate_addr(debug_target_if *, uint64_t, MemoryAccessType type);
void exec_thread(thread_func, char = 'g');
std::vector<debug_target_if *> run_threads(std::vector<debug_target_if *>, bool = false);
void writeall(int, char *, size_t);
void send_packet(int, const char *, gdb_kind_t = GDB_KIND_PACKET);
void retransmit(int);
void dispatch(int conn);
void serve(void);
void run(void);
};
#endif
================================================
FILE: vp/src/core/common/gdb-mc/handler.cpp
================================================
#include <assert.h>
#include <stdlib.h>
#include <limits.h>
#include <libgdb/parser2.h>
#include "debug.h"
#include "gdb_server.h"
#include "register_format.h"
enum {
GDB_PKTSIZ = 4096,
GDB_PC_REG = 32,
};
std::map<std::string, GDBServer::packet_handler> handlers {
{ "?", &GDBServer::haltReason },
{ "g", &GDBServer::getRegisters },
{ "H", &GDBServer::setThread },
{ "k", &GDBServer::killServer },
{ "m", &GDBServer::readMemory },
{ "M", &GDBServer::writeMemory },
{ "p", &GDBServer::readRegister },
{ "qAttached", &GDBServer::qAttached },
{ "qSupported", &GDBServer::qSupported },
{ "qfThreadInfo", &GDBServer::threadInfo },
{ "qsThreadInfo", &GDBServer::threadInfoEnd },
{ "T", &GDBServer::isAlive },
{ "vCont", &GDBServer::vCont },
{ "vCont?", &GDBServer::vContSupported },
{ "z", &GDBServer::removeBreakpoint },
{ "Z", &GDBServer::setBreakpoint },
};
void GDBServer::haltReason(int conn, gdb_command_t *cmd) {
(void)cmd;
// If n is a recognized stop reason […]. The aa should be
// ‘05’, the trap signal. At most one stop reason should be
// present.
// TODO: Only send create conditionally.
send_packet(conn, "S05");
}
void GDBServer::getRegisters(int conn, gdb_command_t *cmd) {
(void)cmd;
auto formatter = new RegisterFormater(arch);
auto fn = [formatter] (debug_target_if *hart) {
for (uint64_t v : hart->get_registers())
formatter->formatRegister(v);
};
exec_thread(fn);
send_packet(conn, formatter->str().c_str());
delete formatter;
}
void GDBServer::setThread(int conn, gdb_command_t *cmd) {
gdb_cmd_h_t *hcmd;
hcmd = &cmd->v.hcmd;
thread_ops[hcmd->op] = hcmd->id.tid;
send_packet(conn, "OK");
}
void GDBServer::killServer(int conn, gdb_command_t *cmd) {
(void)conn;
(void)cmd;
// TODO: Stop the System C simulation instead of
// terminating the program. This would require interacting
// with the GDBServerRunner directly to make it exit.
//
// This could be implemented by adding sys_exit to
// debug_target_if, however, some SystemC modules, e.g. FU540_PLIC
// also spawn threads which are not stopped at all. These
// modules need to be fixed first.
exit(EXIT_SUCCESS);
}
void GDBServer::readMemory(int conn, gdb_command_t *cmd) {
gdb_memory_t *mem;
mem = &cmd->v.mem;
assert(mem->addr <= UINT64_MAX);
assert(mem->length <= UINT_MAX);
std::string retval;
auto fn = [this, &retval, mem] (debug_target_if *hart) {
uint64_t addr = translate_addr(hart, mem->addr, LOAD);
retval += memory->read_memory(addr, (unsigned)mem->length);
};
try {
exec_thread(fn);
} catch (const std::runtime_error&) { /* exception raised in fn */
send_packet(conn, "E01");
return;
}
send_packet(conn, retval.c_str());
}
void GDBServer::writeMemory(int conn, gdb_command_t *cmd) {
gdb_memory_t *loc;
gdb_memory_write_t *mem;
mem = &cmd->v.memw;
loc = &mem->location;
assert(loc->addr <= UINT64_MAX);
assert(loc->length <= UINT_MAX);
auto fn = [this, loc, mem] (debug_target_if *hart) {
uint64_t addr = translate_addr(hart, loc->addr, STORE);
memory->write_memory(addr, (unsigned)loc->length, mem->data);
};
try {
exec_thread(fn);
} catch (const std::runtime_error&) {
send_packet(conn, "E01");
return;
}
send_packet(conn, "OK");
}
void GDBServer::readRegister(int conn, gdb_command_t *cmd) {
int reg;
auto formatter = new RegisterFormater(arch);
reg = cmd->v.ival;
auto fn = [formatter, reg] (debug_target_if *hart) {
uint64_t regval;
if (reg == GDB_PC_REG) {
regval = hart->get_progam_counter();
} else {
regval = hart->read_register(reg);
}
/* TODO: handle CSRs? */
formatter->formatRegister(regval);
};
try {
exec_thread(fn);
} catch (const std::out_of_range&) { /* exception raised in fn */
send_packet(conn, "E01");
goto ret;
}
send_packet(conn, formatter->str().c_str());
ret:
delete formatter;
}
void GDBServer::threadInfo(int conn, gdb_command_t *cmd) {
(void)cmd;
std::string thrlist = "m";
/* TODO: refactor this to make it always output hex digits,
* preferablly move it to the protocol code/ */
for (size_t i = 0; i < harts.size(); i++) {
debug_target_if *hart = harts.at(i);
if (hart->get_status() == CoreExecStatus::Terminated)
continue;
thrlist += std::to_string(hart->get_hart_id() + 1);
if (i + 1 < harts.size())
thrlist += ",";
}
send_packet(conn, thrlist.c_str());
}
void GDBServer::threadInfoEnd(int conn, gdb_command_t *cmd) {
(void)cmd;
// GDB will respond to each reply with a request for more thread
// ids (using the ‘qs’ form of the query), until the target
// responds with ‘l’ (lower-case ell, for last).
//
// Since the GDBServer::threadInfo sends all threads in one
// response we always terminate the list here.
send_packet(conn, "l");
}
void GDBServer::qAttached(int conn, gdb_command_t *cmd) {
(void)cmd;
// 0 process started, 1 attached to process
send_packet(conn, "0");
}
void GDBServer::qSupported(int conn, gdb_command_t *cmd) {
(void)cmd;
send_packet(conn, ("vContSupported+;PacketSize=" + std::to_string(GDB_PKTSIZ)).c_str());
}
void GDBServer::isAlive(int conn, gdb_command_t *cmd) {
gdb_thread_t *thr;
thr = &cmd->v.tval;
try {
get_threads(thr->tid);
} catch (const std::out_of_range&) {
send_packet(conn, "E01");
return;
}
send_packet(conn, "OK");
}
void GDBServer::vCont(int conn, gdb_command_t *cmd) {
gdb_vcont_t *vcont;
int stopped_thread = -1;
const char *stop_reason = NULL;
std::map<debug_target_if *, bool> matched;
/* This handler attempts to implement the all-stop mode.
* See: https://sourceware.org/gdb/onlinedocs/gdb/All_002dStop-Mode.html */
vcont = cmd->v.vval;
for (vcont = cmd->v.vval; vcont; vcont = vcont->next) {
bool single = false;
if (vcont->action == 's')
single = true;
else if (vcont->action != 'c')
throw std::invalid_argument("Unimplemented vCont action"); /* TODO */
std::vector<debug_target_if *> selected_harts;
try {
auto run = get_threads(vcont->thread.tid);
for (auto i = run.begin(); i != run.end();) {
debug_target_if *hart = *i;
if (matched.count(hart))
i = run.erase(i); /* already matched */
else
i++;
}
selected_harts = run_threads(run, single);
} catch (const std::out_of_range&) {
send_packet(conn, "E01");
return;
}
for (debug_target_if *hart : selected_harts) {
switch (hart->get_status()) {
case CoreExecStatus::HitBreakpoint:
stop_reason = "05";
stopped_thread = hart->get_hart_id() + 1;
/* mark runnable again */
hart->set_status(CoreExecStatus::Runnable);
break;
case CoreExecStatus::Terminated:
stop_reason = "03";
stopped_thread = hart->get_hart_id() + 1;
break;
case CoreExecStatus::Runnable:
continue;
}
}
/* The vCont specification mandates that only the leftmost action with
* a matching thread-id is applied. Unfortunately, the specification
* is a bit unclear in regards to handling two actions with no thread
* id (i.e. GDB_THREAD_ALL). */
if (vcont->thread.tid > 0) {
auto threads = get_threads(vcont->thread.tid);
assert(threads.size() == 1);
matched[threads.front()] = true;
}
}
assert(stop_reason && stopped_thread >= 1);
/* This sets the current thread for various follow-up
* operations, most importantly readRegister. Without this
* change gdb reads the registers of the previously selected
* thread and doesn't switch threads properly if a thread other
* than the currently selected hits a breakpoint.
*
* XXX: No idea if the stub is really required to do this. */
thread_ops['g'] = stopped_thread;
const std::string msg = std::string("T") + stop_reason + "thread:" +
std::to_string(stopped_thread) + ";";
send_packet(conn, msg.c_str());
}
void GDBServer::vContSupported(int conn, gdb_command_t *cmd) {
(void)cmd;
// We need to support both c and C otherwise GDB doesn't use vCont
// This is documented in the remote_vcont_probe function in the GDB source.
send_packet(conn, "vCont;c;C");
}
void GDBServer::removeBreakpoint(int conn, gdb_command_t *cmd) {
gdb_breakpoint_t *bpoint;
bpoint = &cmd->v.bval;
if (bpoint->type != GDB_ZKIND_SOFT) {
send_packet(conn, ""); /* not supported */
return;
}
for (debug_target_if *hart : harts)
hart->remove_breakpoint(bpoint->address);
send_packet(conn, "OK");
}
void GDBServer::setBreakpoint(int conn, gdb_command_t *cmd) {
gdb_breakpoint_t *bpoint;
bpoint = &cmd->v.bval;
if (bpoint->type != GDB_ZKIND_SOFT) {
send_packet(conn, ""); /* not supported */
return;
}
for (debug_target_if *hart : harts)
hart->insert_breakpoint(bpoint->address);
send_packet(conn, "OK");
}
================================================
FILE: vp/src/core/common/gdb-mc/libgdb/CMakeLists.txt
================================================
add_library(gdb
mpc/mpc.c
parser1.c
parser2.c
response.c
util.c)
target_compile_options(gdb PRIVATE
-Wpedantic -Wall -Wextra -Wconversion -Wmissing-prototypes
-Wpointer-arith -Wstrict-prototypes -Wshadow -Wcast-align)
set_source_files_properties(mpc/mpc.c
PROPERTIES COMPILE_FLAGS "-w -ansi")
target_include_directories(gdb PRIVATE
${CMAKE_CURRENT_SOURCE_DIR}/mpc)
target_include_directories(gdb PUBLIC
${CMAKE_CURRENT_SOURCE_DIR}/include)
================================================
FILE: vp/src/core/common/gdb-mc/libgdb/README.md
================================================
# libgdb
Utility library for implementing the [GDB protocol][gdb protocol].
## Design
Unfortunately, the GDB protocol doesn't use delimiters for protocol
messages. For this reason, a state machine is required to read packets
from a stream. This library implements such a state machine using a
parser combinator library. This state machine only returns a generic
package structure and doesn't perform any further canonicalization.
Since proper canonicalization of GDB packets is desirable this utility
library provides two parser stages. The first stage is the
aforementioned state machine, the second parser stages performs packet
specific validations and uses the most restrictive input definition on a
per packet basis.
This library attempts to follow some of the [langsec][langsec website]
principles outlined in [\[1\]][curing the vulnerable parsers].
Unfortunately, the second stage parser is unfinished at the moment and
has a fallback for accepting arbitrary inputs currently, thereby
circumventing the "most restrictive input definition".
Additionally, some utility functions for creating responses to received
GDB packets are provided by `libgdb/response.h`. However, this part of
the library is in very early stages of development.
[gdb protocol]: https://sourceware.org/gdb/onlinedocs/gdb/Remote-Protocol.html
[langsec website]: http://langsec.org/
[curing the vulnerable parsers]: https://www.usenix.org/publications/login/spring2017/bratus
================================================
FILE: vp/src/core/common/gdb-mc/libgdb/include/libgdb/parser1.h
================================================
#ifndef LIBGDB_PARSER1_H
#define LIBGDB_PARSER1_H
#ifdef __cplusplus
extern "C" {
#endif
#include <stdio.h>
#include <stddef.h>
#include <stdbool.h>
#define GDB_CSUM_LEN 2
typedef enum {
GDB_KIND_NOTIFY,
GDB_KIND_PACKET,
GDB_KIND_NACK,
GDB_KIND_ACK,
} gdb_kind_t;
typedef struct {
gdb_kind_t kind;
char *data;
char csum[GDB_CSUM_LEN];
} gdb_packet_t;
void gdb_free_packet(gdb_packet_t *);
gdb_packet_t *gdb_parse_pkt(FILE *);
#ifdef __cplusplus
}
#endif
#endif
================================================
FILE: vp/src/core/common/gdb-mc/libgdb/include/libgdb/parser2.h
================================================
#ifndef LIBGDB_PARSER2_H
#define LIBGDB_PARSER2_H
#ifdef __cplusplus
extern "C" {
#endif
#include <stddef.h>
#include <stdint.h>
#include <inttypes.h>
#include <libgdb/parser1.h>
#ifndef LIBGDB_ADDR_TYPE
#define LIBGDB_ADDR_TYPE uint64_t
#endif
#ifndef LIBGDB_ADDR_FORMAT
#define LIBGDB_ADDR_FORMAT SCNx64
#endif
typedef LIBGDB_ADDR_TYPE gdb_addr_t;
#undef LIBGDB_ADDR_TYPE
enum {
GDB_THREAD_UNSET = -2,
GDB_THREAD_ANY = 0,
GDB_THREAD_ALL = -1,
};
typedef struct {
int pid; /* requires multiprocess feature */
int tid;
} gdb_thread_t;
typedef enum {
GDB_ZKIND_SOFT = 0,
GDB_ZKIND_HARD,
GDB_ZKIND_WATCHW,
GDB_ZKIND_WATCHR,
GDB_ZKIND_WATCHA,
} gdb_ztype_t;
typedef struct {
gdb_ztype_t type;
gdb_addr_t address;
size_t kind;
} gdb_breakpoint_t;
typedef struct {
gdb_addr_t addr;
size_t length;
} gdb_memory_t;
typedef struct {
gdb_memory_t location;
char *data; /* null-terminated hexstring */
} gdb_memory_write_t;
typedef struct {
char op;
gdb_thread_t id;
} gdb_cmd_h_t;
typedef struct _gdb_vcont_t gdb_vcont_t;
struct _gdb_vcont_t {
char action;
int sig; /* -1 if unset */
gdb_thread_t thread;
gdb_vcont_t *next; /* NULL on end */
};
typedef enum {
GDB_ARG_NONE,
GDB_ARG_VCONT,
GDB_ARG_H,
GDB_ARG_INT,
GDB_ARG_MEMORY,
GDB_ARG_MEMORYW,
GDB_ARG_BREAK,
GDB_ARG_THREAD,
} gdb_argument_t;
typedef struct {
char *name;
gdb_argument_t type;
union {
gdb_vcont_t *vval;
gdb_cmd_h_t hcmd;
int ival;
gdb_memory_t mem;
gdb_memory_write_t memw;
gdb_breakpoint_t bval;
gdb_thread_t tval;
} v;
} gdb_command_t;
void gdb_free_cmd(gdb_command_t *);
gdb_command_t *gdb_parse_cmd(gdb_packet_t *);
#ifdef __cplusplus
}
#endif
#endif
================================================
FILE: vp/src/core/common/gdb-mc/libgdb/include/libgdb/response.h
================================================
#ifndef LIBGDB_RESPONSE_H
#define LIBGDB_RESPONSE_H
#ifdef __cplusplus
extern "C" {
#endif
/* Copied from QEMU
* See: https://github.com/qemu/qemu/blob/d37147997/gdbstub.c#L103-L113 */
typedef enum {
GDB_SIGNAL_0 = 0,
GDB_SIGNAL_INT = 2,
GDB_SIGNAL_QUIT = 3,
GDB_SIGNAL_TRAP = 5,
GDB_SIGNAL_ABRT = 6,
GDB_SIGNAL_ALRM = 14,
GDB_SIGNAL_IO = 23,
GDB_SIGNAL_XCPU = 24,
GDB_SIGNAL_UNKNOWN = 143
} gdb_signal_t;
char *gdb_serialize(gdb_kind_t, const char *);
#ifdef __cplusplus
}
#endif
#endif
================================================
FILE: vp/src/core/common/gdb-mc/libgdb/internal.h
================================================
#ifndef GDB_PROTOCOL_FNS
#define GDB_PROTOCOL_FNS
#include <assert.h>
#include <stddef.h>
#include <libgdb/parser2.h>
#ifdef NDEBUG
#define xassert(X) ((void)(X)) /* prevent -Wunused-parameter warning */
#else
#define xassert(X) (assert(X))
#endif
void *xrealloc(void *, size_t);
void *xmalloc(size_t);
char *xstrdup(char *);
gdb_command_t *gdb_new_cmd(char *, gdb_argument_t);
int calc_csum(const char *);
bool gdb_is_valid(gdb_packet_t *);
char *gdb_unescape(char *);
char *gdb_decode_runlen(char *);
#endif
================================================
FILE: vp/src/core/common/gdb-mc/libgdb/parser1.c
================================================
#include <stdio.h>
#include <stdlib.h>
#include <stdint.h>
#include <libgdb/parser1.h>
#include "mpc.h"
#include "internal.h"
static mpc_val_t *
gdbf_packet(int n, mpc_val_t** xs)
{
gdb_packet_t *pkt;
char *start, *csum;
xassert(n == 3);
pkt = xmalloc(sizeof(*pkt));
pkt->data = (char*)xs[1];
start = (char*)xs[0];
switch (*start) {
case '%':
pkt->kind = GDB_KIND_NOTIFY;
break;
case '$':
pkt->kind = GDB_KIND_PACKET;
break;
default:
xassert(0);
}
csum = (char*)xs[2];
csum++; /* skip leading '#' */
memcpy(pkt->csum, csum, GDB_CSUM_LEN);
/* data (xs[1]) is still used in struct, don't free it */
free(xs[0]);
free(xs[2]);
return pkt;
}
static mpc_val_t *
gdbf_acknowledge(mpc_val_t* xs)
{
gdb_packet_t *pkt;
char *str;
pkt = xmalloc(sizeof(*pkt));
pkt->data = NULL;
memset(pkt->csum, 0, GDB_CSUM_LEN);
str = (char*)xs;
switch (*str) {
case '+':
pkt->kind = GDB_KIND_ACK;
break;
case '-':
pkt->kind = GDB_KIND_NACK;
break;
default:
xassert(0);
}
free(xs);
return pkt;
}
static mpc_parser_t *
gdb_csum(void)
{
mpc_parser_t *csum;
csum = mpc_and(2, mpcf_strfold, mpc_any(), mpc_any(), free);
return mpc_and(2, mpcf_strfold, mpc_char('#'), csum, free);
}
static mpc_parser_t *
gdb_packet(void)
{
mpc_parser_t *data;
data = mpc_many(mpcf_strfold, mpc_noneof("#$"));
return mpc_and(3, gdbf_packet, mpc_char('$'),
data, gdb_csum(), free, free);
}
static mpc_parser_t *
gdb_notification(void)
{
mpc_parser_t *data;
data = mpc_many(mpcf_strfold, mpc_noneof("#$%"));
return mpc_and(3, gdbf_packet, mpc_char('%'),
data, gdb_csum(), free, free);
}
static mpc_parser_t *
gdb_acknowledge(void)
{
return mpc_apply(mpc_oneof("+-"), gdbf_acknowledge);
}
static mpc_parser_t *
gdb_parse_stage1(void)
{
return mpc_or(3, gdb_acknowledge(),
gdb_packet(),
gdb_notification());
}
gdb_packet_t *
gdb_parse_pkt(FILE *stream)
{
gdb_packet_t *pkt;
mpc_parser_t *par;
mpc_result_t r;
pkt = NULL;
par = mpc_predictive(gdb_parse_stage1());
if (mpc_parse_pipe("<stream>", stream, par, &r)) {
pkt = (gdb_packet_t *)r.output;
} else {
#ifdef GDB_PARSER_DEBUG
mpc_err_print(r.error);
#endif
mpc_err_delete(r.error);
}
mpc_cleanup(1, par);
return pkt;
}
================================================
FILE: vp/src/core/common/gdb-mc/libgdb/parser2.c
================================================
#include <errno.h>
#include <stdlib.h>
#include <string.h>
#include <libgdb/parser1.h>
#include <libgdb/parser2.h>
#include "mpc.h"
#include "parser2.h"
#include "internal.h"
static mpc_val_t *
gdbf_ignarg(mpc_val_t* xs)
{
char *str, *sep;
gdb_command_t *cmd;
str = (char *)xs;
if ((sep = strchr(str, ':')))
*sep = '\0';
cmd = gdb_new_cmd(xstrdup(str), GDB_ARG_NONE);
free(xs);
return cmd;
}
static mpc_val_t *
gdbf_address(mpc_val_t *x)
{
int r;
gdb_addr_t *v;
v = xmalloc(sizeof(*v));
r = sscanf((char *)x, "%"LIBGDB_ADDR_FORMAT, v);
xassert(r == 1);
free(x);
return v;
}
static mpc_parser_t *
gdb_address(void)
{
return mpc_expect(mpc_apply(mpc_hexdigits(), gdbf_address), "hexadecimal address");
}
static mpc_val_t *
gdbf_uhex(mpc_val_t *x)
{
int r;
size_t *v;
v = xmalloc(sizeof(*v));
r = sscanf((char *)x, "%zx", v);
xassert(r == 1);
free(x);
return v;
}
static mpc_parser_t *
gdb_uhex(void)
{
return mpc_apply(mpc_hexdigits(), gdbf_uhex);
}
static mpc_val_t *
gdbf_negative(mpc_val_t *val)
{
int *neg;
xassert(!strcmp((char*)val, "-1"));
neg = xmalloc(sizeof(*neg));
*neg = -1;
free(val);
return neg;
}
static mpc_val_t *
gdbf_memory(int n, mpc_val_t **xs)
{
gdb_memory_t *mem;
xassert(n == 3);
xassert(*(char *)xs[1] == ',');
mem = xmalloc(sizeof(*mem));
mem->addr = *((gdb_addr_t *)xs[0]);
mem->length = *((size_t *)xs[2]);
free(xs[0]);
free(xs[1]);
free(xs[2]);
return mem;
}
static mpc_parser_t *
gdb_memory(void)
{
return mpc_and(3, gdbf_memory, gdb_address(),
mpc_char(','), gdb_uhex(),
free, free);
}
static mpc_val_t *
gdbf_thread_id(int n, mpc_val_t** xs)
{
int *arg1, *arg2;
gdb_thread_t *id;
xassert(n == 2);
id = xmalloc(sizeof(*id));
arg1 = (int*)xs[0];
arg2 = (int*)xs[1];
if (arg1 != NULL)
id->pid = *arg1;
else
id->pid = GDB_THREAD_UNSET;
id->tid = *arg2;
free(xs[0]);
free(xs[1]);
return id;
}
static mpc_parser_t *
gdb_hexid(void)
{
/* Positive numbers with a target-specific interpretation,
* formatted as big-endian hex strings. Can also be a literal
* '-1' to indicate all threads, or '0' to pick any thread. */
return mpc_or(2, mpc_hex(),
mpc_apply(mpc_string("-1"), gdbf_negative));
}
static mpc_parser_t *
gdb_thread_id(void)
{
mpc_parser_t *pid, *tid;
tid = gdb_hexid();
pid = mpc_and(3, mpcf_snd_free, mpc_char('p'),
gdb_hexid(), mpc_char('.'), free, free);
return mpc_and(2, gdbf_thread_id, mpc_maybe(pid), tid, free);
}
gdbf_fold(h, GDB_ARG_H, GDBF_ARG_HCMD)
static mpc_parser_t *
gdb_packet_h(void)
{
mpc_parser_t *op, *id;
op = mpc_any(); /* (‘m’, ‘M’, ‘g’, ‘G’, et.al.). */
id = gdb_thread_id();
return mpc_and(3, gdbf_packet_h, mpc_char('H'), op, id, free, free);
}
gdbf_fold(p, GDB_ARG_INT, GDBF_ARG_INT)
static mpc_parser_t *
gdb_packet_p(void)
{
return mpc_and(2, gdbf_packet_p, mpc_char('p'), mpc_hex(), free);
}
static mpc_val_t *
gdbf_vcont_action(int n, mpc_val_t **xs)
{
char *actstr;
size_t actlen;
gdb_vcont_t *vcont;
xassert(n == 2);
actstr = (char *)xs[0];
actlen = strlen(actstr);
vcont = xmalloc(sizeof(*vcont));
vcont->action = *actstr;
vcont->next = NULL;
if (actlen == 1)
vcont->sig = -1;
else if (actlen == 3)
vcont->sig = (int)strtol(actstr + 1, NULL, 16);
else
xassert(0);
/* An action with no thread-id matches all threads. */
if (!xs[1]) {
vcont->thread.pid = GDB_THREAD_UNSET;
vcont->thread.tid = GDB_THREAD_ALL;
} else {
vcont->thread = *((gdb_thread_t *)xs[1]);
}
free(xs[0]);
free(xs[1]);
return vcont;
}
static mpc_val_t *
gdbf_vcont(int n, mpc_val_t **xs)
{
size_t i;
gdb_vcont_t *vcont;
xassert(n >= 1);
for (vcont = (gdb_vcont_t *)xs[0], i = 1; i < (size_t)n; i++, vcont = vcont->next)
vcont->next = (gdb_vcont_t *)xs[i];
vcont->next = NULL;
return (gdb_vcont_t *)xs[0];
}
gdbf_fold(vcont, GDB_ARG_VCONT, GDBF_ARG_VCONT)
static mpc_parser_t *
gdb_packet_vcont(void)
{
mpc_parser_t *action0, *action1, *action, *args, *thread;
/* TODO: add support for r command */
action0 = mpc_oneof("cst");
action1 = mpc_and(2, mpcf_strfold, mpc_oneof("CS"), mpc_hexdigits());
thread = mpc_and(2, mpcf_snd_free, mpc_char(':'), gdb_thread_id(), free);
action = mpc_and(2, gdbf_vcont_action, mpc_or(2, action0, action1),
mpc_maybe(thread), free); /* destructor incorrect but unused */
args = mpc_many1(gdbf_vcont, mpc_and(2, mpcf_snd_free, mpc_char(';'), action, free));
return mpc_and(2, gdbf_packet_vcont, mpc_string("vCont"), args, free);
}
gdbf_fold(m, GDB_ARG_MEMORY, GDBF_ARG_MEMORY)
static mpc_parser_t *
gdb_packet_m(void)
{
return mpc_and(2, gdbf_packet_m, mpc_char('m'), gdb_memory(), free);
}
gdbf_fold(M, GDB_ARG_MEMORYW, GDBF_ARG_MEMORYW)
static mpc_parser_t *
gdb_packet_M(void)
{
return mpc_and(4, gdbf_packet_M, mpc_char('M'),
gdb_memory(), mpc_char(':'), mpc_hexdigits(),
free, free, free);
}
static mpc_parser_t *
gdb_arg(mpc_parser_t *par)
{
return mpc_and(2, mpcf_fst_free, par, mpc_char(','), free);
}
gdbf_fold(z, GDB_ARG_BREAK, GDBF_ARG_BREAK)
static mpc_parser_t *
gdb_packet_z(void)
{
mpc_parser_t *name, *type;
/* TODO: parse cond_list */
name = mpc_or(2, mpc_char('z'), mpc_char('Z'));
type = mpc_apply(mpc_re("[0-4]"), mpcf_int);
return mpc_and(4, gdbf_packet_z, name,
gdb_arg(type), gdb_arg(gdb_address()),
gdb_uhex(), free, free, free);
}
gdbf_fold(T, GDB_ARG_THREAD, GDBF_ARG_THREAD)
static mpc_parser_t *
gdb_packet_T(void)
{
return mpc_and(2, gdbf_packet_T, mpc_char('T'),
gdb_thread_id(), free);
}
static mpc_parser_t *
gdb_any(void)
{
return mpc_apply(mpc_many1(mpcf_strfold, mpc_any()), gdbf_ignarg);
}
static mpc_parser_t *
gdb_cmd(mpc_parser_t *cmd)
{
return mpc_and(2, mpcf_fst_free, cmd, mpc_eoi(), gdb_free_cmd);
}
static mpc_parser_t *
gdb_parse_stage2(void)
{
return mpc_or(8,
gdb_cmd(gdb_packet_h()),
gdb_cmd(gdb_packet_p()),
gdb_cmd(gdb_packet_vcont()),
gdb_cmd(gdb_packet_m()),
gdb_cmd(gdb_packet_M()),
gdb_cmd(gdb_packet_z()),
gdb_cmd(gdb_packet_T()),
gdb_any());
}
gdb_command_t *
gdb_parse_cmd(gdb_packet_t *pkt)
{
mpc_result_t r;
mpc_parser_t *par;
char *data, *unesc;
gdb_command_t *cmd;
cmd = NULL;
par = gdb_parse_stage2();
if (pkt->kind != GDB_KIND_PACKET) {
errno = EINVAL;
return NULL;
}
if (!gdb_is_valid(pkt)) {
errno = EILSEQ;
return NULL;
}
if (!(data = gdb_decode_runlen(pkt->data))) {
errno = EBADMSG;
return NULL;
}
unesc = gdb_unescape(data);
free(data);
if (mpc_parse("<packet>", unesc, par, &r)) {
cmd = (gdb_command_t *)r.output;
} else {
#ifdef GDB_PARSER_DEBUG
mpc_err_print(r.error);
#endif
mpc_err_delete(r.error);
}
free(unesc);
mpc_cleanup(1, par);
if (!cmd)
errno = EBADMSG; /* mpc_parse failed */
return cmd;
}
================================================
FILE: vp/src/core/common/gdb-mc/libgdb/parser2.h
================================================
#define gdbf_fold(I, TYPE, FUNC) \
static mpc_val_t *gdbf_packet_##I(int n, mpc_val_t **xs) \
{ \
int j; \
gdb_command_t *cmd; \
\
/* Remove optional mpc_maybe() arguments */ \
for (j = n - 1; j >= 0; j--) \
if (!xs[j]) \
--n; \
\
xassert(n > 0); \
cmd = gdb_new_cmd(xs[0], TYPE); \
FUNC; \
\
return cmd; \
}
#define GDBF_ARG_HCMD \
do { \
xassert(n == 3); \
\
cmd->v.hcmd.op = *((char*)xs[1]); \
cmd->v.hcmd.id = *((gdb_thread_t*)xs[2]); \
\
free(xs[1]); \
free(xs[2]); \
} while (0)
#define GDBF_ARG_INT \
do { \
xassert(n == 2); \
\
cmd->v.ival = *((int*)xs[1]); \
free(xs[1]); \
} while (0)
#define GDBF_ARG_VCONT \
do { \
xassert(n == 2); \
cmd->v.vval = (gdb_vcont_t *)xs[1]; \
} while (0)
#define GDBF_ARG_MEMORY \
do { \
xassert(n == 2); \
cmd->v.mem = *((gdb_memory_t *)xs[1]); \
free(xs[1]); \
} while (0)
#define GDBF_ARG_MEMORYW \
do { \
xassert(n == 4); \
cmd->v.memw.location = *((gdb_memory_t *)xs[1]); \
cmd->v.memw.data = (char *)xs[3]; \
free(xs[1]); \
free(xs[2]); \
} while (0)
#define GDBF_ARG_BREAK \
do { \
int type; \
\
xassert(n == 4); \
type = *(int *)(xs[1]); \
xassert(type >= GDB_ZKIND_SOFT && type <= GDB_ZKIND_WATCHA); \
\
cmd->v.bval.type = (gdb_ztype_t)type; \
cmd->v.bval.address = *((gdb_addr_t *)xs[2]); \
cmd->v.bval.kind = *(size_t *)(xs[3]); \
free(xs[1]); \
free(xs[2]); \
free(xs[3]); \
} while (0)
#define GDBF_ARG_THREAD \
do { \
xassert(n == 2); \
cmd->v.tval = *((gdb_thread_t *)xs[1]); \
free(xs[1]); \
} while (0)
================================================
FILE: vp/src/core/common/gdb-mc/libgdb/response.c
================================================
#include <err.h>
#include <stdlib.h>
#include <stddef.h>
#include <string.h>
#include <stdio.h>
#include <libgdb/parser1.h>
#include <libgdb/response.h>
#include "internal.h"
static char
kind_to_char(gdb_kind_t kind)
{
switch (kind) {
case GDB_KIND_NOTIFY:
return '#';
case GDB_KIND_PACKET:
return '$';
case GDB_KIND_NACK:
return '-';
case GDB_KIND_ACK:
return '+';
default:
xassert(0);
return -1;
}
}
char *
gdb_serialize(gdb_kind_t kind, const char *data)
{
size_t pktlen;
char *serialized;
char pktkind;
int csum, ret;
pktkind = kind_to_char(kind);
if (kind == GDB_KIND_NACK || kind == GDB_KIND_ACK) {
xassert(data == NULL);
serialized = xmalloc(2); /* kind + nullbyte */
serialized[0] = pktkind;
serialized[1] = '\0';
return serialized;
}
csum = calc_csum(data);
/* + 3 → nullbyte, checksum delimiter, kind */
pktlen = strlen(data) + GDB_CSUM_LEN + 3;
serialized = xmalloc(pktlen);
ret = snprintf(serialized, pktlen, "%c%s#%.2x", pktkind, data, csum);
if (ret < 0)
err(EXIT_FAILURE, "snprintf failed");
else if ((size_t)ret >= pktlen)
errx(EXIT_FAILURE, "insufficient snprintf buffer size");
return serialized;
}
================================================
FILE: vp/src/core/common/gdb-mc/libgdb/util.c
================================================
#include <err.h>
#include <limits.h>
#include <stdio.h>
#include <string.h>
#include <stddef.h>
#include <stdbool.h>
#include <stdlib.h>
#include <stdbool.h>
#include <libgdb/parser1.h>
#include <libgdb/parser2.h>
#include "internal.h"
#define GDB_RUNLEN_CHAR '*'
#define GDB_RUNLEN_OFF 29
#define GDB_RUNLEN_STEP 32
#define GDB_ESCAPE_CHAR '}'
#define GDB_ESCAPE_BYTE 0x20
int
calc_csum(const char *data)
{
size_t i;
int csum = 0;
for (i = 0; i < strlen(data); i++)
csum += (int)data[i];
return csum % 256;
}
char *
gdb_decode_runlen(char *data)
{
int rcount, j;
size_t i, nlen, nrem;
int runlen;
char *ndat;
nlen = 0;
nrem = strlen(data);
ndat = xmalloc(nrem);
for (runlen = -1, i = 0; i < strlen(data); i++) {
if (data[i] == GDB_RUNLEN_CHAR) {
if (i <= 0)
goto err;
runlen = data[i - 1];
continue;
}
if (runlen == -1) {
runlen = data[i];
rcount = 1;
} else {
rcount = (int)data[i] - GDB_RUNLEN_OFF;
if (rcount <= 0)
goto err;
}
for (j = 0; j < rcount; j++) {
if (nrem-- == 0) {
ndat = xrealloc(ndat, nlen + GDB_RUNLEN_STEP);
nrem += GDB_RUNLEN_STEP;
}
xassert(runlen >= 0 && runlen <= CHAR_MAX);
ndat[nlen++] = (char)runlen;
}
runlen = -1;
}
/* shrink to actual size */
ndat = xrealloc(ndat, nlen + 1);
ndat[nlen] = '\0';
return ndat;
err:
free(ndat);
return NULL;
}
char *
gdb_unescape(char *data)
{
size_t i, nlen;
char *ndat;
bool esc;
ndat = xmalloc(strlen(data));
nlen = 0;
for (esc = false, i = 0; i < strlen(data); i++) {
if (data[i] == GDB_ESCAPE_CHAR) {
esc = true;
continue;
}
ndat[nlen++] = (esc) ? data[i] ^ GDB_ESCAPE_BYTE : data[i];
esc = false;
}
/* shrink to actual size */
ndat = xrealloc(ndat, nlen + 1);
ndat[nlen] = '\0';
return ndat;
}
bool
gdb_is_valid(gdb_packet_t *pkt)
{
int ret;
int expcsum;
char strcsum[GDB_CSUM_LEN + 1]; /* +1 for snprintf nullbyte */
if (!pkt->data)
return true;
expcsum = calc_csum(pkt->data);
ret = snprintf(strcsum, sizeof(strcsum), "%.2x", expcsum);
xassert(ret == GDB_CSUM_LEN);
return !strncmp(pkt->csum, strcsum, GDB_CSUM_LEN);
}
gdb_command_t *
gdb_new_cmd(char *name, gdb_argument_t type)
{
gdb_command_t *cmd;
cmd = xmalloc(sizeof(*cmd));
cmd->name = name;
cmd->type = type;
return cmd;
}
void
gdb_free_cmd(gdb_command_t *cmd)
{
gdb_vcont_t *parent, *next;
if (cmd->type == GDB_ARG_MEMORYW)
free(cmd->v.memw.data);
if (cmd->type == GDB_ARG_VCONT) {
parent = cmd->v.vval;
while (parent) {
next = parent->next;
free(parent);
parent = next;
}
}
free(cmd->name);
free(cmd);
}
void *
xrealloc(void *ptr, size_t size)
{
void *r;
if (!(r = realloc(ptr, size)))
err(EXIT_FAILURE, "realloc failed");
return r;
}
void *
xmalloc(size_t size)
{
void *r;
if (!(r = malloc(size)))
err(EXIT_FAILURE, "malloc failed");
return r;
}
char *
xstrdup(char *s)
{
char *r;
if (!(r = strdup(s)))
err(EXIT_FAILURE, "strdup failed");
return r;
}
void
gdb_free_packet(gdb_packet_t *pkt)
{
if (pkt->data)
free(pkt->data);
free(pkt);
}
================================================
FILE: vp/src/core/common/gdb-mc/register_format.cpp
================================================
#include <iomanip>
#include <byteswap.h>
#include "register_format.h"
RegisterFormater::RegisterFormater(Architecture arch) {
this->arch = arch;
this->stream << std::setfill('0') << std::hex;
}
void RegisterFormater::formatRegister(uint64_t value) {
switch (arch) {
case RV32:
stream << std::setw(8) << bswap_32(value);
break;
case RV64:
stream << std::setw(16) << bswap_64(value);
break;
default:
throw std::invalid_argument("Architecture not implemented");
}
}
std::string RegisterFormater::str(void) {
return this->stream.str();
}
================================================
FILE: vp/src/core/common/gdb-mc/register_format.h
================================================
#ifndef RISCV_GDB_REGISTER
#define RISCV_GDB_REGISTER
#include <sstream>
#include <stdint.h>
#include "core_defs.h"
class RegisterFormater {
private:
Architecture arch;
std::ostringstream stream;
public:
RegisterFormater(Architecture);
void formatRegister(uint64_t);
std::string str(void);
};
#endif
================================================
FILE: vp/src/core/common/instr.cpp
================================================
#include "instr.h"
#include "trap.h"
#include "util/common.h"
#include <cassert>
#include <stdexcept>
constexpr uint32_t LUI_MASK = 0b00000000000000000000000001111111;
constexpr uint32_t LUI_ENCODING = 0b00000000000000000000000000110111;
constexpr uint32_t AUIPC_MASK = 0b00000000000000000000000001111111;
constexpr uint32_t AUIPC_ENCODING = 0b00000000000000000000000000010111;
constexpr uint32_t JAL_MASK = 0b00000000000000000000000001111111;
constexpr uint32_t JAL_ENCODING = 0b00000000000000000000000001101111;
constexpr uint32_t JALR_MASK = 0b00000000000000000111000001111111;
constexpr uint32_t JALR_ENCODING = 0b00000000000000000000000001100111;
constexpr uint32_t BEQ_MASK = 0b00000000000000000111000001111111;
constexpr uint32_t BEQ_ENCODING = 0b00000000000000000000000001100011;
constexpr uint32_t BNE_MASK = 0b00000000000000000111000001111111;
constexpr uint32_t BNE_ENCODING = 0b00000000000000000001000001100011;
constexpr uint32_t BLT_MASK = 0b00000000000000000111000001111111;
constexpr uint32_t BLT_ENCODING = 0b00000000000000000100000001100011;
constexpr uint32_t BGE_MASK = 0b00000000000000000111000001111111;
constexpr uint32_t BGE_ENCODING = 0b00000000000000000101000001100011;
constexpr uint32_t BLTU_MASK = 0b00000000000000000111000001111111;
constexpr uint32_t BLTU_ENCODING = 0b00000000000000000110000001100011;
constexpr uint32_t BGEU_MASK = 0b00000000000000000111000001111111;
constexpr uint32_t BGEU_ENCODING = 0b00000000000000000111000001100011;
constexpr uint32_t LB_MASK = 0b00000000000000000111000001111111;
constexpr uint32_t LB_ENCODING = 0b00000000000000000000000000000011;
constexpr uint32_t LH_MASK = 0b00000000000000000111000001111111;
constexpr uint32_t LH_ENCODING = 0b00000000000000000001000000000011;
constexpr uint32_t LW_MASK = 0b00000000000000000111000001111111;
constexpr uint32_t LW_ENCODING = 0b00000000000000000010000000000011;
constexpr uint32_t LBU_MASK = 0b00000000000000000111000001111111;
constexpr uint32_t LBU_ENCODING = 0b00000000000000000100000000000011;
constexpr uint32_t LHU_MASK = 0b00000000000000000111000001111111;
constexpr uint32_t LHU_ENCODING = 0b00000000000000000101000000000011;
constexpr uint32_t SB_MASK = 0b00000000000000000111000001111111;
constexpr uint32_t SB_ENCODING = 0b00000000000000000000000000100011;
constexpr uint32_t SH_MASK = 0b00000000000000000111000001111111;
constexpr uint32_t SH_ENCODING = 0b00000000000000000001000000100011;
constexpr uint32_t SW_MASK = 0b00000000000000000111000001111111;
constexpr uint32_t SW_ENCODING = 0b00000000000000000010000000100011;
constexpr uint32_t ADDI_MASK = 0b00000000000000000111000001111111;
constexpr uint32_t ADDI_ENCODING = 0b00000000000000000000000000010011;
constexpr uint32_t SLTI_MASK = 0b00000000000000000111000001111111;
constexpr uint32_t SLTI_ENCODING = 0b00000000000000000010000000010011;
constexpr uint32_t SLTIU_MASK = 0b00000000000000000111000001111111;
constexpr uint32_t SLTIU_ENCODING = 0b00000000000000000011000000010011;
constexpr uint32_t XORI_MASK = 0b00000000000000000111000001111111;
constexpr uint32_t XORI_ENCODING = 0b00000000000000000100000000010011;
constexpr uint32_t ORI_MASK = 0b00000000000000000111000001111111;
constexpr uint32_t ORI_ENCODING = 0b00000000000000000110000000010011;
constexpr uint32_t ANDI_MASK = 0b00000000000000000111000001111111;
constexpr uint32_t ANDI_ENCODING = 0b00000000000000000111000000010011;
//-- RV64 special case (one less mask bit compared to RV32)
constexpr uint32_t SLLI_MASK = 0b11111100000000000111000001111111;
constexpr uint32_t SLLI_ENCODING = 0b00000000000000000001000000010011;
constexpr uint32_t SRLI_MASK = 0b11111100000000000111000001111111;
constexpr uint32_t SRLI_ENCODING = 0b00000000000000000101000000010011;
constexpr uint32_t SRAI_MASK = 0b11111100000000000111000001111111;
constexpr uint32_t SRAI_ENCODING = 0b01000000000000000101000000010011;
//-- RV32 case
constexpr uint32_t SLLI_32_MASK = 0b11111110000000000111000001111111;
constexpr uint32_t SLLI_32_ENCODING = 0b00000000000000000001000000010011;
constexpr uint32_t SRLI_32_MASK = 0b11111110000000000111000001111111;
constexpr uint32_t SRLI_32_ENCODING = 0b00000000000000000101000000010011;
constexpr uint32_t SRAI_32_MASK = 0b11111110000000000111000001111111;
constexpr uint32_t SRAI_32_ENCODING = 0b01000000000000000101000000010011;
//--
constexpr uint32_t ADD_MASK = 0b11111110000000000111000001111111;
constexpr uint32_t ADD_ENCODING = 0b00000000000000000000000000110011;
constexpr uint32_t SUB_MASK = 0b11111110000000000111000001111111;
constexpr uint32_t SUB_ENCODING = 0b01000000000000000000000000110011;
constexpr uint32_t SLL_MASK = 0b11111110000000000111000001111111;
constexpr uint32_t SLL_ENCODING = 0b00000000000000000001000000110011;
constexpr uint32_t SLT_MASK = 0b11111110000000000111000001111111;
constexpr uint32_t SLT_ENCODING = 0b00000000000000000010000000110011;
constexpr uint32_t SLTU_MASK = 0b11111110000000000111000001111111;
constexpr uint32_t SLTU_ENCODING = 0b00000000000000000011000000110011;
constexpr uint32_t XOR_MASK = 0b11111110000000000111000001111111;
constexpr uint32_t XOR_ENCODING = 0b00000000000000000100000000110011;
constexpr uint32_t SRL_MASK = 0b11111110000000000111000001111111;
constexpr uint32_t SRL_ENCODING = 0b00000000000000000101000000110011;
constexpr uint32_t SRA_MASK = 0b11111110000000000111000001111111;
constexpr uint32_t SRA_ENCODING = 0b01000000000000000101000000110011;
constexpr uint32_t OR_MASK = 0b11111110000000000111000001111111;
constexpr uint32_t OR_ENCODING = 0b00000000000000000110000000110011;
constexpr uint32_t AND_MASK = 0b11111110000000000111000001111111;
constexpr uint32_t AND_ENCODING = 0b00000000000000000111000000110011;
constexpr uint32_t FENCE_MASK = 0b00000000000000000111000001111111;
constexpr uint32_t FENCE_ENCODING = 0b00000000000000000000000000001111;
constexpr uint32_t FENCE_I_MASK = 0b00000000000000000111000001111111;
constexpr uint32_t FENCE_I_ENCODING = 0b00000000000000000001000000001111;
constexpr uint32_t ECALL_MASK = 0b11111111111111111111111111111111;
constexpr uint32_t ECALL_ENCODING = 0b00000000000000000000000001110011;
constexpr uint32_t EBREAK_MASK = 0b11111111111111111111111111111111;
constexpr uint32_t EBREAK_ENCODING = 0b00000000000100000000000001110011;
constexpr uint32_t CSRRW_MASK = 0b00000000000000000111000001111111;
constexpr uint32_t CSRRW_ENCODING = 0b00000000000000000001000001110011;
constexpr uint32_t CSRRS_MASK = 0b00000000000000000111000001111111;
constexpr uint32_t CSRRS_ENCODING = 0b00000000000000000010000001110011;
constexpr uint32_t CSRRC_MASK = 0b00000000000000000111000001111111;
constexpr uint32_t CSRRC_ENCODING = 0b00000000000000000011000001110011;
constexpr uint32_t CSRRWI_MASK = 0b00000000000000000111000001111111;
constexpr uint32_t CSRRWI_ENCODING = 0b00000000000000000101000001110011;
constexpr uint32_t CSRRSI_MASK = 0b00000000000000000111000001111111;
constexpr uint32_t CSRRSI_ENCODING = 0b00000000000000000110000001110011;
constexpr uint32_t CSRRCI_MASK = 0b00000000000000000111000001111111;
constexpr uint32_t CSRRCI_ENCODING = 0b00000000000000000111000001110011;
constexpr uint32_t MUL_MASK = 0b11111110000000000111000001111111;
constexpr uint32_t MUL_ENCODING = 0b00000010000000000000000000110011;
constexpr uint32_t MULH_MASK = 0b11111110000000000111000001111111;
constexpr uint32_t MULH_ENCODING = 0b00000010000000000001000000110011;
constexpr uint32_t MULHSU_MASK = 0b11111110000000000111000001111111;
constexpr uint32_t MULHSU_ENCODING = 0b00000010000000000010000000110011;
constexpr uint32_t MULHU_MASK = 0b11111110000000000111000001111111;
constexpr uint32_t MULHU_ENCODING = 0b00000010000000000011000000110011;
constexpr uint32_t DIV_MASK = 0b11111110000000000111000001111111;
constexpr uint32_t DIV_ENCODING = 0b00000010000000000100000000110011;
constexpr uint32_t DIVU_MASK = 0b11111110000000000111000001111111;
constexpr uint32_t DIVU_ENCODING = 0b00000010000000000101000000110011;
constexpr uint32_t REM_MASK = 0b11111110000000000111000001111111;
constexpr uint32_t REM_ENCODING = 0b00000010000000000110000000110011;
constexpr uint32_t REMU_MASK = 0b11111110000000000111000001111111;
constexpr uint32_t REMU_ENCODING = 0b00000010000000000111000000110011;
constexpr uint32_t LR_W_MASK = 0b11111001111100000111000001111111;
constexpr uint32_t LR_W_ENCODING = 0b00010000000000000010000000101111;
constexpr uint32_t SC_W_MASK = 0b11111000000000000111000001111111;
constexpr uint32_t SC_W_ENCODING = 0b00011000000000000010000000101111;
constexpr uint32_t AMOSWAP_W_MASK = 0b11111000000000000111000001111111;
constexpr uint32_t AMOSWAP_W_ENCODING = 0b00001000000000000010000000101111;
constexpr uint32_t AMOADD_W_MASK = 0b11111000000000000111000001111111;
constexpr uint32_t AMOADD_W_ENCODING = 0b00000000000000000010000000101111;
constexpr uint32_t AMOXOR_W_MASK = 0b11111000000000000111000001111111;
constexpr uint32_t AMOXOR_W_ENCODING = 0b00100000000000000010000000101111;
constexpr uint32_t AMOAND_W_MASK = 0b11111000000000000111000001111111;
constexpr uint32_t AMOAND_W_ENCODING = 0b01100000000000000010000000101111;
constexpr uint32_t AMOOR_W_MASK = 0b11111000000000000111000001111111;
constexpr uint32_t AMOOR_W_ENCODING = 0b01000000000000000010000000101111;
constexpr uint32_t AMOMIN_W_MASK = 0b11111000000000000111000001111111;
constexpr uint32_t AMOMIN_W_ENCODING = 0b10000000000000000010000000101111;
constexpr uint32_t AMOMAX_W_MASK = 0b11111000000000000111000001111111;
constexpr uint32_t AMOMAX_W_ENCODING = 0b10100000000000000010000000101111;
constexpr uint32_t AMOMINU_W_MASK = 0b11111000000000000111000001111111;
constexpr uint32_t AMOMINU_W_ENCODING = 0b11000000000000000010000000101111;
constexpr uint32_t AMOMAXU_W_MASK = 0b11111000000000000111000001111111;
constexpr uint32_t AMOMAXU_W_ENCODING = 0b11100000000000000010000000101111;
constexpr uint32_t URET_MASK = 0b11111111111111111111111111111111;
constexpr uint32_t URET_ENCODING = 0b00000000001000000000000001110011;
constexpr uint32_t SRET_MASK = 0b11111111111111111111111111111111;
constexpr uint32_t SRET_ENCODING = 0b00010000001000000000000001110011;
constexpr uint32_t MRET_MASK = 0b11111111111111111111111111111111;
constexpr uint32_t MRET_ENCODING = 0b00110000001000000000000001110011;
constexpr uint32_t WFI_MASK = 0b11111111111111111111111111111111;
constexpr uint32_t WFI_ENCODING = 0b00010000010100000000000001110011;
constexpr uint32_t SFENCE_VMA_MASK = 0b11111110000000000111111111111111;
constexpr uint32_t SFENCE_VMA_ENCODING = 0b00010010000000000000000001110011;
//-- RV64IMA Extension
constexpr uint32_t LWU_MASK = 0b00000000000000000111000001111111;
constexpr uint32_t LWU_ENCODING = 0b00000000000000000110000000000011;
constexpr uint32_t LD_MASK = 0b00000000000000000111000001111111;
constexpr uint32_t LD_ENCODING = 0b00000000000000000011000000000011;
constexpr uint32_t SD_MASK = 0b00000000000000000111000001111111;
constexpr uint32_t SD_ENCODING = 0b00000000000000000011000000100011;
constexpr uint32_t ADDIW_MASK = 0b00000000000000000111000001111111;
constexpr uint32_t ADDIW_ENCODING = 0b00000000000000000000000000011011;
constexpr uint32_t SLLIW_MASK = 0b11111110000000000111000001111111;
constexpr uint32_t SLLIW_ENCODING = 0b00000000000000000001000000011011;
constexpr uint32_t SRLIW_MASK = 0b11111110000000000111000001111111;
constexpr uint32_t SRLIW_ENCODING = 0b00000000000000000101000000011011;
constexpr uint32_t SRAIW_MASK = 0b11111110000000000111000001111111;
constexpr uint32_t SRAIW_ENCODING = 0b01000000000000000101000000011011;
constexpr uint32_t ADDW_MASK = 0b11111110000000000111000001111111;
constexpr uint32_t ADDW_ENCODING = 0b00000000000000000000000000111011;
constexpr uint32_t SUBW_MASK = 0b11111110000000000111000001111111;
constexpr uint32_t SUBW_ENCODING = 0b01000000000000000000000000111011;
constexpr uint32_t SLLW_MASK = 0b11111110000000000111000001111111;
constexpr uint32_t SLLW_ENCODING = 0b00000000000000000001000000111011;
constexpr uint32_t SRLW_MASK = 0b11111110000000000111000001111111;
constexpr uint32_t SRLW_ENCODING = 0b00000000000000000101000000111011;
constexpr uint32_t SRAW_MASK = 0b11111110000000000111000001111111;
constexpr uint32_t SRAW_ENCODING = 0b01000000000000000101000000111011;
constexpr uint32_t MULW_MASK = 0b11111110000000000111000001111111;
constexpr uint32_t MULW_ENCODING = 0b00000010000000000000000000111011;
constexpr uint32_t DIVW_MASK = 0b11111110000000000111000001111111;
constexpr uint32_t DIVW_ENCODING = 0b00000010000000000100000000111011;
constexpr uint32_t DIVUW_MASK = 0b11111110000000000111000001111111;
constexpr uint32_t DIVUW_ENCODING = 0b00000010000000000101000000111011;
constexpr uint32_t REMW_MASK = 0b11111110000000000111000001111111;
constexpr uint32_t REMW_ENCODING = 0b00000010000000000110000000111011;
constexpr uint32_t REMUW_MASK = 0b11111110000000000111000001111111;
constexpr uint32_t REMUW_ENCODING = 0b00000010000000000111000000111011;
constexpr uint32_t LR_D_MASK = 0b11111001111100000111000001111111;
constexpr uint32_t LR_D_ENCODING = 0b00010000000000000011000000101111;
constexpr uint32_t SC_D_MASK = 0b11111000000000000111000001111111;
constexpr uint32_t SC_D_ENCODING = 0b00011000000000000011000000101111;
constexpr uint32_t AMOSWAP_D_MASK = 0b11111000000000000111000001111111;
constexpr uint32_t AMOSWAP_D_ENCODING = 0b00001000000000000011000000101111;
constexpr uint32_t AMOADD_D_MASK = 0b11111000000000000111000001111111;
constexpr uint32_t AMOADD_D_ENCODING = 0b00000000000000000011000000101111;
constexpr uint32_t AMOXOR_D_MASK = 0b11111000000000000111000001111111;
constexpr uint32_t AMOXOR_D_ENCODING = 0b00100000000000000011000000101111;
constexpr uint32_t AMOAND_D_MASK = 0b11111000000000000111000001111111;
constexpr uint32_t AMOAND_D_ENCODING = 0b01100000000000000011000000101111;
constexpr uint32_t AMOOR_D_MASK = 0b11111000000000000111000001111111;
constexpr uint32_t AMOOR_D_ENCODING = 0b01000000000000000011000000101111;
constexpr uint32_t AMOMIN_D_MASK = 0b11111000000000000111000001111111;
constexpr uint32_t AMOMIN_D_ENCODING = 0b10000000000000000011000000101111;
constexpr uint32_t AMOMAX_D_MASK = 0b11111000000000000111000001111111;
constexpr uint32_t AMOMAX_D_ENCODING = 0b10100000000000000011000000101111;
constexpr uint32_t AMOMINU_D_MASK = 0b11111000000000000111000001111111;
constexpr uint32_t AMOMINU_D_ENCODING = 0b11000000000000000011000000101111;
constexpr uint32_t AMOMAXU_D_MASK = 0b11111000000000000111000001111111;
constexpr uint32_t AMOMAXU_D_ENCODING = 0b11100000000000000011000000101111;
// RV32/64FD Extension
constexpr uint32_t FLW_MASK = 0b00000000000000000111000001111111;
constexpr uint32_t FLW_ENCODING = 0b00000000000000000010000000000111;
constexpr uint32_t FSW_MASK = 0b00000000000000000111000001111111;
constexpr uint32_t FSW_ENCODING = 0b00000000000000000010000000100111;
constexpr uint32_t FMADD_S_MASK = 0b00000110000000000000000001111111;
constexpr uint32_t FMADD_S_ENCODING = 0b00000000000000000000000001000011;
constexpr uint32_t FMSUB_S_MASK = 0b00000110000000000000000001111111;
constexpr uint32_t FMSUB_S_ENCODING = 0b00000000000000000000000001000111;
constexpr uint32_t FNMADD_S_MASK = 0b00000110000000000000000001111111;
constexpr uint32_t FNMADD_S_ENCODING = 0b00000000000000000000000001001111;
constexpr uint32_t FNMSUB_S_MASK = 0b00000110000000000000000001111111;
constexpr uint32_t FNMSUB_S_ENCODING = 0b00000000000000000000000001001011;
constexpr uint32_t FADD_S_MASK = 0b11111110000000000000000001111111;
constexpr uint32_t FADD_S_ENCODING = 0b00000000000000000000000001010011;
constexpr uint32_t FSUB_S_MASK = 0b11111110000000000000000001111111;
constexpr uint32_t FSUB_S_ENCODING = 0b00001000000000000000000001010011;
constexpr uint32_t FMUL_S_MASK = 0b11111110000000000000000001111111;
constexpr uint32_t FMUL_S_ENCODING = 0b00010000000000000000000001010011;
constexpr uint32_t FDIV_S_MASK = 0b11111110000000000000000001111111;
constexpr uint32_t FDIV_S_ENCODING = 0b00011000000000000000000001010011;
constexpr uint32_t FSQRT_S_MASK = 0b11111111111100000000000001111111;
constexpr uint32_t FSQRT_S_ENCODING = 0b01011000000000000000000001010011;
constexpr uint32_t FSGNJ_S_MASK = 0b11111110000000000111000001111111;
constexpr uint32_t FSGNJ_S_ENCODING = 0b00100000000000000000000001010011;
constexpr uint32_t FSGNJN_S_MASK = 0b11111110000000000111000001111111;
constexpr uint32_t FSGNJN_S_ENCODING = 0b00100000000000000001000001010011;
constexpr uint32_t FSGNJX_S_MASK = 0b11111110000000000111000001111111;
constexpr uint32_t FSGNJX_S_ENCODING = 0b00100000000000000010000001010011;
constexpr uint32_t FMIN_S_MASK = 0b11111110000000000111000001111111;
constexpr uint32_t FMIN_S_ENCODING = 0b00101000000000000000000001010011;
constexpr uint32_t FMAX_S_MASK = 0b11111110000000000111000001111111;
constexpr uint32_t FMAX_S_ENCODING = 0b00101000000000000001000001010011;
constexpr uint32_t FCVT_W_S_MASK = 0b11111111111100000000000001111111;
constexpr uint32_t FCVT_W_S_ENCODING = 0b11000000000000000000000001010011;
constexpr uint32_t FCVT_WU_S_MASK = 0b11111111111100000000000001111111;
constexpr uint32_t FCVT_WU_S_ENCODING = 0b11000000000100000000000001010011;
constexpr uint32_t FMV_X_W_MASK = 0b11111111111100000111000001111111;
constexpr uint32_t FMV_X_W_ENCODING = 0b11100000000000000000000001010011;
constexpr uint32_t FEQ_S_MASK = 0b11111110000000000111000001111111;
constexpr uint32_t FEQ_S_ENCODING = 0b10100000000000000010000001010011;
constexpr uint32_t FLT_S_MASK = 0b11111110000000000111000001111111;
constexpr uint32_t FLT_S_ENCODING = 0b10100000000000000001000001010011;
constexpr uint32_t FLE_S_MASK = 0b11111110000000000111000001111111;
constexpr uint32_t FLE_S_ENCODING = 0b10100000000000000000000001010011;
constexpr uint32_t FCLASS_S_MASK = 0b11111111111100000111000001111111;
constexpr uint32_t FCLASS_S_ENCODING = 0b11100000000000000001000001010011;
constexpr uint32_t FCVT_S_W_MASK = 0b11111111111100000000000001111111;
constexpr uint32_t FCVT_S_W_ENCODING = 0b11010000000000000000000001010011;
constexpr uint32_t FCVT_S_WU_MASK = 0b11111111111100000000000001111111;
constexpr uint32_t FCVT_S_WU_ENCODING = 0b11010000000100000000000001010011;
constexpr uint32_t FMV_W_X_MASK = 0b11111111111100000111000001111111;
constexpr uint32_t FMV_W_X_ENCODING = 0b11110000000000000000000001010011;
constexpr uint32_t FCVT_L_S_MASK = 0b11111111111100000000000001111111;
constexpr uint32_t FCVT_L_S_ENCODING = 0b11000000001000000000000001010011;
constexpr uint32_t FCVT_LU_S_MASK = 0b11111111111100000000000001111111;
constexpr uint32_t FCVT_LU_S_ENCODING = 0b11000000001100000000000001010011;
constexpr uint32_t FCVT_S_L_MASK = 0b11111111111100000000000001111111;
constexpr uint32_t FCVT_S_L_ENCODING = 0b11010000001000000000000001010011;
constexpr uint32_t FCVT_S_LU_MASK = 0b11111111111100000000000001111111;
constexpr uint32_t FCVT_S_LU_ENCODING = 0b11010000001100000000000001010011;
constexpr uint32_t FLD_MASK = 0b00000000000000000111000001111111;
constexpr uint32_t FLD_ENCODING = 0b00000000000000000011000000000111;
constexpr uint32_t FSD_MASK = 0b00000000000000000111000001111111;
constexpr uint32_t FSD_ENCODING = 0b00000000000000000011000000100111;
constexpr uint32_t FMADD_D_MASK = 0b00000110000000000000000001111111;
constexpr uint32_t FMADD_D_ENCODING = 0b00000010000000000000000001000011;
constexpr uint32_t FMSUB_D_MASK = 0b00000110000000000000000001111111;
constexpr uint32_t FMSUB_D_ENCODING = 0b00000010000000000000000001000111;
constexpr uint32_t FNMSUB_D_MASK = 0b00000110000000000000000001111111;
constexpr uint32_t FNMSUB_D_ENCODING = 0b00000010000000000000000001001011;
constexpr uint32_t FNMADD_D_MASK = 0b00000110000000000000000001111111;
constexpr uint32_t FNMADD_D_ENCODING = 0b00000010000000000000000001001111;
constexpr uint32_t FADD_D_MASK = 0b11111110000000000000000001111111;
constexpr uint32_t FADD_D_ENCODING = 0b00000010000000000000000001010011;
constexpr uint32_t FSUB_D_MASK = 0b11111110000000000000000001111111;
constexpr uint32_t FSUB_D_ENCODING = 0b00001010000000000000000001010011;
constexpr uint32_t FMUL_D_MASK = 0b11111110000000000000000001111111;
constexpr uint32_t FMUL_D_ENCODING = 0b00010010000000000000000001010011;
constexpr uint32_t FDIV_D_MASK = 0b11111110000000000000000001111111;
constexpr uint32_t FDIV_D_ENCODING = 0b00011010000000000000000001010011;
constexpr uint32_t FSQRT_D_MASK = 0b11111111111100000000000001111111;
constexpr uint32_t FSQRT_D_ENCODING = 0b01011010000000000000000001010011;
constexpr uint32_t FSGNJ_D_MASK = 0b11111110000000000111000001111111;
constexpr uint32_t FSGNJ_D_ENCODING = 0b00100010000000000000000001010011;
constexpr uint32_t FSGNJN_D_MASK = 0b11111110000000000111000001111111;
constexpr uint32_t FSGNJN_D_ENCODING = 0b00100010000000000001000001010011;
constexpr uint32_t FSGNJX_D_MASK = 0b11111110000000000111000001111111;
constexpr uint32_t FSGNJX_D_ENCODING = 0b00100010000000000010000001010011;
constexpr uint32_t FMIN_D_MASK = 0b11111110000000000111000001111111;
constexpr uint32_t FMIN_D_ENCODING = 0b00101010000000000000000001010011;
constexpr uint32_t FMAX_D_MASK = 0b11111110000000000111000001111111;
constexpr uint32_t FMAX_D_ENCODING = 0b00101010000000000001000001010011;
constexpr uint32_t FCVT_S_D_MASK = 0b11111111111100000000000001111111;
constexpr uint32_t FCVT_S_D_ENCODING = 0b01000000000100000000000001010011;
constexpr uint32_t FCVT_D_S_MASK = 0b11111111111100000000000001111111;
constexpr uint32_t FCVT_D_S_ENCODING = 0b01000010000000000000000001010011;
constexpr uint32_t FEQ_D_MASK = 0b11111110000000000111000001111111;
constexpr uint32_t FEQ_D_ENCODING = 0b10100010000000000010000001010011;
constexpr uint32_t FLT_D_MASK = 0b11111110000000000111000001111111;
constexpr uint32_t FLT_D_ENCODING = 0b10100010000000000001000001010011;
constexpr uint32_t FLE_D_MASK = 0b11111110000000000111000001111111;
constexpr uint32_t FLE_D_ENCODING = 0b10100010000000000000000001010011;
constexpr uint32_t FCLASS_D_MASK = 0b11111111111100000111000001111111;
constexpr uint32_t FCLASS_D_ENCODING = 0b11100010000000000001000001010011;
constexpr uint32_t FCVT_W_D_MASK = 0b11111111111100000000000001111111;
constexpr uint32_t FCVT_W_D_ENCODING = 0b11000010000000000000000001010011;
constexpr uint32_t FCVT_WU_D_MASK = 0b11111111111100000000000001111111;
constexpr uint32_t FCVT_WU_D_ENCODING = 0b11000010000100000000000001010011;
constexpr uint32_t FCVT_D_W_MASK = 0b11111111111100000000000001111111;
constexpr uint32_t FCVT_D_W_ENCODING = 0b11010010000000000000000001010011;
constexpr uint32_t FCVT_D_WU_MASK = 0b11111111111100000000000001111111;
constexpr uint32_t FCVT_D_WU_ENCODING = 0b11010010000100000000000001010011;
constexpr uint32_t FCVT_L_D_MASK = 0b11111111111100000000000001111111;
constexpr uint32_t FCVT_L_D_ENCODING = 0b11000010001000000000000001010011;
constexpr uint32_t FCVT_LU_D_MASK = 0b11111111111100000000000001111111;
constexpr uint32_t FCVT_LU_D_ENCODING = 0b11000010001100000000000001010011;
constexpr uint32_t FMV_X_D_MASK = 0b11111111111100000111000001111111;
constexpr uint32_t FMV_X_D_ENCODING = 0b11100010000000000000000001010011;
constexpr uint32_t FCVT_D_L_MASK = 0b11111111111100000000000001111111;
constexpr uint32_t FCVT_D_L_ENCODING = 0b11010010001000000000000001010011;
constexpr uint32_t FCVT_D_LU_MASK = 0b11111111111100000000000001111111;
constexpr uint32_t FCVT_D_LU_ENCODING = 0b11010010001100000000000001010011;
constexpr uint32_t FMV_D_X_MASK = 0b11111111111100000111000001111111;
constexpr uint32_t FMV_D_X_ENCODING = 0b11110010000000000000000001010011;
#define MATCH_AND_RETURN_INSTR2(instr, result) \
if (unlikely((data() & (instr##_MASK)) != (instr##_ENCODING))) \
return UNDEF; \
return result;
#define MATCH_AND_RETURN_INSTR(instr) MATCH_AND_RETURN_INSTR2(instr, instr)
namespace Compressed {
enum Opcode {
// quadrant zero
C_Illegal,
C_Reserved,
C_ADDI4SPN,
C_FLD,
C_LQ, // RV128
C_LW,
C_FLW,
C_LD,
C_FSD,
C_SQ, // RV128
C_SW,
C_FSW,
C_SD,
// quadrant one
C_NOP,
C_ADDI,
C_JAL,
C_ADDIW,
C_LI,
C_ADDI16SP,
C_LUI,
C_SRLI,
C_SRAI,
C_ANDI,
C_SUB,
C_XOR,
C_OR,
C_AND,
C_SUBW,
C_ADDW,
C_J,
C_BEQZ,
C_BNEZ,
// quadrant two
C_SLLI,
C_FLDSP,
C_LQSP, // RV128
C_LWSP,
C_FLWSP,
C_LDSP,
C_JR,
C_MV,
C_EBREAK,
C_JALR,
C_ADD,
C_FSDSP,
C_SQSP, // RV128
C_SWSP,
C_FSWSP,
C_SDSP,
};
}
std::array<const char*, 32> Opcode::regnamePrettyStr = {
"zero", "ra", "sp", "gp", "tp", "t0", "t1", "t2",
"s0/fp", "s1", "a0", "a1", "a2", "a3", "a4", "a5",
"a6", "a7", "s2", "s3", "s4", "s5", "s6", "s7",
"s8", "s9", "s10", "s11", "t3", "t4", "t5", "t6"
};
/*
Python snippet to generate the "mappingStr":
for e in [e.strip().replace(",", "") for e in s.strip().split("\n")]:
if "//" in e or
gitextract_zs0_rad3/
├── .clang-format
├── .gitignore
├── .gitlab-ci.yml
├── .gitmodules
├── CITATION.cff
├── Dockerfile
├── LICENSE
├── Makefile
├── README.md
├── env/
│ └── basic/
│ └── vp-display/
│ ├── CMakeLists.txt
│ ├── VP-Display.pro
│ ├── framebuffer.h
│ ├── main.cpp
│ ├── mainwindow.cpp
│ ├── mainwindow.h
│ ├── mainwindow.ui
│ ├── vpdisplayserver.cpp
│ └── vpdisplayserver.h
├── sw/
│ ├── .gitignore
│ ├── Makefile
│ ├── Makefile.common
│ ├── README.md
│ ├── basic-asm/
│ │ ├── Makefile
│ │ └── sum.S
│ ├── basic-c/
│ │ ├── Makefile
│ │ ├── bootstrap.S
│ │ ├── main.c
│ │ └── sum.c
│ ├── basic-debug/
│ │ ├── Makefile
│ │ ├── bootstrap.S
│ │ ├── eclipse-remote-debug-readme.txt
│ │ ├── main.c
│ │ ├── remote-debug-readme.txt
│ │ └── test-ignore
│ ├── basic-dma/
│ │ ├── Makefile
│ │ ├── bootstrap.S
│ │ ├── irq.c
│ │ ├── irq.h
│ │ └── main.c
│ ├── basic-e/
│ │ ├── Makefile
│ │ └── sum.S
│ ├── basic-gcov/
│ │ ├── Makefile
│ │ └── test-ignore
│ ├── basic-gpio/
│ │ ├── Makefile
│ │ ├── bootstrap.S
│ │ ├── gpio.h
│ │ ├── link.ld
│ │ ├── main.c
│ │ ├── platform.h
│ │ ├── uart.c
│ │ ├── uart.h
│ │ ├── util.c
│ │ └── util.h
│ ├── basic-multicore/
│ │ ├── Makefile
│ │ ├── bootstrap.S
│ │ └── main.c
│ ├── blocking-sleep/
│ │ ├── Makefile
│ │ ├── bootstrap.S
│ │ ├── irq.S
│ │ └── main.c
│ ├── busy-wait-sleep/
│ │ ├── Makefile
│ │ ├── bootstrap.S
│ │ └── main.c
│ ├── c++-lib/
│ │ ├── Makefile
│ │ └── main.cpp
│ ├── clock-ticks/
│ │ ├── Makefile
│ │ ├── bootstrap.S
│ │ ├── irq.c
│ │ ├── irq.h
│ │ └── main.c
│ ├── crc8/
│ │ ├── Makefile
│ │ ├── bootstrap.S
│ │ ├── link.ld
│ │ ├── main.c
│ │ ├── platform.h
│ │ ├── uart.c
│ │ ├── uart.h
│ │ ├── util.c
│ │ └── util.h
│ ├── flashTest/
│ │ ├── Makefile
│ │ ├── main.cpp
│ │ └── test-ignore
│ ├── mramTest/
│ │ ├── Makefile
│ │ └── main.cpp
│ ├── mrv32-uart/
│ │ ├── Makefile
│ │ ├── bootstrap.S
│ │ ├── link.ld
│ │ ├── main.c
│ │ ├── platform.h
│ │ ├── uart.c
│ │ ├── uart.h
│ │ ├── util.c
│ │ └── util.h
│ ├── peripheral-in-the-loop/
│ │ ├── Makefile
│ │ └── main.c
│ ├── printf/
│ │ ├── Makefile
│ │ ├── entry.S
│ │ └── main.c
│ ├── simple-display/
│ │ ├── Makefile
│ │ ├── libDisplay.cpp
│ │ ├── libDisplay.hpp
│ │ ├── main.cpp
│ │ └── test-ignore
│ ├── simple-scheduler/
│ │ ├── Makefile
│ │ ├── cor.S
│ │ ├── main.c
│ │ └── no-clib/
│ │ ├── Makefile
│ │ ├── bootstrap.S
│ │ ├── cor.S
│ │ └── main.c
│ ├── simple-sensor/
│ │ ├── Makefile
│ │ ├── bootstrap.S
│ │ ├── irq.c
│ │ ├── irq.h
│ │ └── main.c
│ ├── sys-read/
│ │ ├── Makefile
│ │ ├── main.c
│ │ └── test-ignore
│ └── test.sh
└── vp/
├── .gitignore
├── CMakeLists.txt
├── cmake/
│ └── AddGitSubmodule.cmake
└── src/
├── CMakeLists.txt
├── core/
│ ├── CMakeLists.txt
│ ├── common/
│ │ ├── CMakeLists.txt
│ │ ├── bus_lock_if.h
│ │ ├── clint.h
│ │ ├── clint_if.h
│ │ ├── core_defs.h
│ │ ├── debug.h
│ │ ├── debug_memory.cpp
│ │ ├── debug_memory.h
│ │ ├── dmi.h
│ │ ├── elf_loader.h
│ │ ├── fp.h
│ │ ├── gdb-mc/
│ │ │ ├── CMakeLists.txt
│ │ │ ├── gdb_runner.cpp
│ │ │ ├── gdb_runner.h
│ │ │ ├── gdb_server.cpp
│ │ │ ├── gdb_server.h
│ │ │ ├── handler.cpp
│ │ │ ├── libgdb/
│ │ │ │ ├── CMakeLists.txt
│ │ │ │ ├── README.md
│ │ │ │ ├── include/
│ │ │ │ │ └── libgdb/
│ │ │ │ │ ├── parser1.h
│ │ │ │ │ ├── parser2.h
│ │ │ │ │ └── response.h
│ │ │ │ ├── internal.h
│ │ │ │ ├── parser1.c
│ │ │ │ ├── parser2.c
│ │ │ │ ├── parser2.h
│ │ │ │ ├── response.c
│ │ │ │ └── util.c
│ │ │ ├── register_format.cpp
│ │ │ └── register_format.h
│ │ ├── instr.cpp
│ │ ├── instr.h
│ │ ├── irq_if.h
│ │ ├── load_if.h
│ │ ├── mmu.h
│ │ ├── mmu_mem_if.h
│ │ ├── rawmode.cpp
│ │ ├── rawmode.h
│ │ ├── real_clint.cpp
│ │ ├── real_clint.h
│ │ ├── timer.cpp
│ │ ├── timer.h
│ │ └── trap.h
│ ├── rv32/
│ │ ├── CMakeLists.txt
│ │ ├── csr.h
│ │ ├── elf_loader.h
│ │ ├── iss.cpp
│ │ ├── iss.h
│ │ ├── mem.h
│ │ ├── mem_if.h
│ │ ├── mmu.h
│ │ ├── syscall.cpp
│ │ ├── syscall.h
│ │ ├── syscall_if.h
│ │ └── timing/
│ │ ├── timing_external.h
│ │ └── timing_simple.h
│ └── rv64/
│ ├── CMakeLists.txt
│ ├── csr.h
│ ├── elf_loader.h
│ ├── iss.cpp
│ ├── iss.h
│ ├── mem.h
│ ├── mem_if.h
│ ├── mmu.h
│ ├── syscall.cpp
│ ├── syscall.h
│ └── syscall_if.h
├── platform/
│ ├── CMakeLists.txt
│ ├── basic/
│ │ ├── CMakeLists.txt
│ │ ├── basic_timer.h
│ │ ├── display.cpp
│ │ ├── display.hpp
│ │ ├── dma.h
│ │ ├── ethernet.cpp
│ │ ├── ethernet.h
│ │ ├── flash.h
│ │ ├── main.cpp
│ │ ├── random_source.h
│ │ ├── sensor.h
│ │ └── sensor2.h
│ ├── common/
│ │ ├── CMakeLists.txt
│ │ ├── async_event.h
│ │ ├── bus.h
│ │ ├── fd_abstract_uart.cpp
│ │ ├── fd_abstract_uart.h
│ │ ├── fe310_plic.cpp
│ │ ├── fe310_plic.h
│ │ ├── fu540_plic.cpp
│ │ ├── fu540_plic.h
│ │ ├── memory.h
│ │ ├── memory_mapped_file.h
│ │ ├── options.cpp
│ │ ├── options.h
│ │ ├── slip.cpp
│ │ ├── slip.h
│ │ ├── terminal.h
│ │ ├── uart.cpp
│ │ ├── uart.h
│ │ ├── uart16550.h
│ │ ├── uart_if.cpp
│ │ ├── uart_if.h
│ │ └── util.h
│ ├── hifive/
│ │ ├── CMakeLists.txt
│ │ ├── aon.h
│ │ ├── can/
│ │ │ ├── 90-slcan.rules
│ │ │ ├── CAN-Howto.md
│ │ │ ├── cantest.cpp
│ │ │ ├── mcp_can_dfs.h
│ │ │ ├── slcan_add.sh
│ │ │ └── slcan_remove.sh
│ │ ├── can.cpp
│ │ ├── can.h
│ │ ├── gpio.cpp
│ │ ├── gpio.h
│ │ ├── hifive_main.cpp
│ │ ├── maskROM.h
│ │ ├── oled/
│ │ │ ├── common.cpp
│ │ │ ├── common.hpp
│ │ │ ├── oled.cpp
│ │ │ └── oled.hpp
│ │ ├── otp.h
│ │ ├── prci.h
│ │ ├── spi.h
│ │ ├── tunnel-uart.cpp
│ │ └── tunnel-uart.hpp
│ ├── hwitl/
│ │ ├── CMakeLists.txt
│ │ ├── main.cpp
│ │ ├── virtual_bus_tlm_connector.cpp
│ │ └── virtual_bus_tlm_connector.hpp
│ ├── linux/
│ │ ├── CMakeLists.txt
│ │ ├── linux_main.cpp
│ │ └── prci.h
│ ├── linux32/
│ │ ├── CMakeLists.txt
│ │ ├── linux32_main.cpp
│ │ └── prci.h
│ ├── microrv32/
│ │ ├── CMakeLists.txt
│ │ ├── main.cpp
│ │ ├── microrv32_gpio.h
│ │ ├── microrv32_led.h
│ │ └── microrv32_uart.h
│ ├── test32/
│ │ ├── CMakeLists.txt
│ │ ├── htif.h
│ │ └── test32_main.cpp
│ ├── tiny32/
│ │ ├── CMakeLists.txt
│ │ └── tiny32_main.cpp
│ ├── tiny32-mc/
│ │ ├── CMakeLists.txt
│ │ └── mc_main.cpp
│ ├── tiny64/
│ │ ├── CMakeLists.txt
│ │ └── tiny64_main.cpp
│ └── tiny64-mc/
│ ├── CMakeLists.txt
│ └── mc_main.cpp
├── util/
│ ├── common.h
│ ├── elegantEnums.cpp
│ ├── elegantEnums.hpp
│ ├── gtkwave_riscv-filter/
│ │ ├── .gitignore
│ │ ├── CMakeLists.txt
│ │ └── riscv-filter.cpp
│ ├── gtkwave_riscv-filter.py
│ ├── memory_map.h
│ ├── options.h
│ └── tlm_map.h
└── vendor/
├── CMakeLists.txt
└── softfloat/
├── CMakeLists.txt
├── f128_add.c
├── f128_classify.c
├── f128_div.c
├── f128_eq.c
├── f128_eq_signaling.c
├── f128_isSignalingNaN.c
├── f128_le.c
├── f128_le_quiet.c
├── f128_lt.c
├── f128_lt_quiet.c
├── f128_mul.c
├── f128_mulAdd.c
├── f128_rem.c
├── f128_roundToInt.c
├── f128_sqrt.c
├── f128_sub.c
├── f128_to_f16.c
├── f128_to_f32.c
├── f128_to_f64.c
├── f128_to_i32.c
├── f128_to_i32_r_minMag.c
├── f128_to_i64.c
├── f128_to_i64_r_minMag.c
├── f128_to_ui32.c
├── f128_to_ui32_r_minMag.c
├── f128_to_ui64.c
├── f128_to_ui64_r_minMag.c
├── f16_add.c
├── f16_div.c
├── f16_eq.c
├── f16_eq_signaling.c
├── f16_isSignalingNaN.c
├── f16_le.c
├── f16_le_quiet.c
├── f16_lt.c
├── f16_lt_quiet.c
├── f16_mul.c
├── f16_mulAdd.c
├── f16_rem.c
├── f16_roundToInt.c
├── f16_sqrt.c
├── f16_sub.c
├── f16_to_f128.c
├── f16_to_f32.c
├── f16_to_f64.c
├── f16_to_i32.c
├── f16_to_i32_r_minMag.c
├── f16_to_i64.c
├── f16_to_i64_r_minMag.c
├── f16_to_ui32.c
├── f16_to_ui32_r_minMag.c
├── f16_to_ui64.c
├── f16_to_ui64_r_minMag.c
├── f32_add.c
├── f32_classify.c
├── f32_div.c
├── f32_eq.c
├── f32_eq_signaling.c
├── f32_isSignalingNaN.c
├── f32_le.c
├── f32_le_quiet.c
├── f32_lt.c
├── f32_lt_quiet.c
├── f32_mul.c
├── f32_mulAdd.c
├── f32_rem.c
├── f32_roundToInt.c
├── f32_sqrt.c
├── f32_sub.c
├── f32_to_f128.c
├── f32_to_f16.c
├── f32_to_f64.c
├── f32_to_i32.c
├── f32_to_i32_r_minMag.c
├── f32_to_i64.c
├── f32_to_i64_r_minMag.c
├── f32_to_ui32.c
├── f32_to_ui32_r_minMag.c
├── f32_to_ui64.c
├── f32_to_ui64_r_minMag.c
├── f64_add.c
├── f64_classify.c
├── f64_div.c
├── f64_eq.c
├── f64_eq_signaling.c
├── f64_isSignalingNaN.c
├── f64_le.c
├── f64_le_quiet.c
├── f64_lt.c
├── f64_lt_quiet.c
├── f64_mul.c
├── f64_mulAdd.c
├── f64_rem.c
├── f64_roundToInt.c
├── f64_sqrt.c
├── f64_sub.c
├── f64_to_f128.c
├── f64_to_f16.c
├── f64_to_f32.c
├── f64_to_i32.c
├── f64_to_i32_r_minMag.c
├── f64_to_i64.c
├── f64_to_i64_r_minMag.c
├── f64_to_ui32.c
├── f64_to_ui32_r_minMag.c
├── f64_to_ui64.c
├── f64_to_ui64_r_minMag.c
├── i32_to_f128.c
├── i32_to_f16.c
├── i32_to_f32.c
├── i32_to_f64.c
├── i64_to_f128.c
├── i64_to_f16.c
├── i64_to_f32.c
├── i64_to_f64.c
├── include/
│ └── softfloat/
│ ├── internals.h
│ ├── platform.h
│ ├── primitiveTypes.h
│ ├── primitives.h
│ ├── softfloat.h
│ ├── softfloat.hpp
│ ├── softfloat_types.h
│ └── specialize.h
├── s_add128.c
├── s_add256M.c
├── s_addCarryM.c
├── s_addComplCarryM.c
├── s_addM.c
├── s_addMagsF128.c
├── s_addMagsF16.c
├── s_addMagsF32.c
├── s_addMagsF64.c
├── s_approxRecip32_1.c
├── s_approxRecipSqrt32_1.c
├── s_approxRecipSqrt_1Ks.c
├── s_approxRecip_1Ks.c
├── s_commonNaNToF128UI.c
├── s_commonNaNToF16UI.c
├── s_commonNaNToF32UI.c
├── s_commonNaNToF64UI.c
├── s_compare128M.c
├── s_compare96M.c
├── s_countLeadingZeros16.c
├── s_countLeadingZeros32.c
├── s_countLeadingZeros64.c
├── s_countLeadingZeros8.c
├── s_eq128.c
├── s_f128UIToCommonNaN.c
├── s_f16UIToCommonNaN.c
├── s_f32UIToCommonNaN.c
├── s_f64UIToCommonNaN.c
├── s_le128.c
├── s_lt128.c
├── s_mul128By32.c
├── s_mul128MTo256M.c
├── s_mul128To256M.c
├── s_mul64ByShifted32To128.c
├── s_mul64To128.c
├── s_mul64To128M.c
├── s_mulAddF128.c
├── s_mulAddF16.c
├── s_mulAddF32.c
├── s_mulAddF64.c
├── s_negXM.c
├── s_normRoundPackToF128.c
├── s_normRoundPackToF16.c
├── s_normRoundPackToF32.c
├── s_normRoundPackToF64.c
├── s_normSubnormalF128Sig.c
├── s_normSubnormalF16Sig.c
├── s_normSubnormalF32Sig.c
├── s_normSubnormalF64Sig.c
├── s_propagateNaNF128UI.c
├── s_propagateNaNF16UI.c
├── s_propagateNaNF32UI.c
├── s_propagateNaNF64UI.c
├── s_remStepMBy32.c
├── s_roundMToI64.c
├── s_roundMToUI64.c
├── s_roundPackMToI64.c
├── s_roundPackMToUI64.c
├── s_roundPackToF128.c
├── s_roundPackToF16.c
├── s_roundPackToF32.c
├── s_roundPackToF64.c
├── s_roundPackToI32.c
├── s_roundPackToI64.c
├── s_roundPackToUI32.c
├── s_roundPackToUI64.c
├── s_roundToI32.c
├── s_roundToI64.c
├── s_roundToUI32.c
├── s_roundToUI64.c
├── s_shiftRightJam128.c
├── s_shiftRightJam128Extra.c
├── s_shiftRightJam256M.c
├── s_shiftRightJam32.c
├── s_shiftRightJam64.c
├── s_shiftRightJam64Extra.c
├── s_shortShiftLeft128.c
├── s_shortShiftLeft64To96M.c
├── s_shortShiftRight128.c
├── s_shortShiftRightExtendM.c
├── s_shortShiftRightJam128.c
├── s_shortShiftRightJam128Extra.c
├── s_shortShiftRightJam64.c
├── s_shortShiftRightJam64Extra.c
├── s_shortShiftRightM.c
├── s_sub128.c
├── s_sub1XM.c
├── s_sub256M.c
├── s_subM.c
├── s_subMagsF128.c
├── s_subMagsF16.c
├── s_subMagsF32.c
├── s_subMagsF64.c
├── softfloat_raiseFlags.c
├── softfloat_state.c
├── ui32_to_f128.c
├── ui32_to_f16.c
├── ui32_to_f32.c
├── ui32_to_f64.c
├── ui64_to_f128.c
├── ui64_to_f16.c
├── ui64_to_f32.c
└── ui64_to_f64.c
SYMBOL INDEX (934 symbols across 369 files)
FILE: env/basic/vp-display/framebuffer.h
function getBackground (line 8) | struct Framebuffer {
FILE: env/basic/vp-display/main.cpp
function main (line 4) | int main(int argc, char *argv[]) {
FILE: env/basic/vp-display/mainwindow.h
function namespace (line 6) | namespace Ui {
function class (line 10) | class VPDisplay : public QWidget {
FILE: env/basic/vp-display/vpdisplayserver.cpp
function Framebuffer (line 16) | Framebuffer* VPDisplayserver::createSM() {
FILE: env/basic/vp-display/vpdisplayserver.h
function class (line 7) | class VPDisplayserver {
FILE: sw/basic-c/main.c
function main (line 6) | int main() {
FILE: sw/basic-c/sum.c
function sum (line 1) | int sum(int end) {
FILE: sw/basic-debug/main.c
function f (line 4) | int f(int a, int b) {
function main (line 13) | int main() {
FILE: sw/basic-dma/irq.c
function irq_empty_handler (line 16) | static void irq_empty_handler() {}
function level_1_interrupt_handler (line 28) | void level_1_interrupt_handler(uint32_t cause) {
function register_interrupt_handler (line 60) | void register_interrupt_handler(uint32_t irq_id, irq_handler_t fn) {
function register_timer_interrupt_handler (line 70) | void register_timer_interrupt_handler(irq_handler_t fn) {
FILE: sw/basic-dma/main.c
function dma_irq_handler (line 20) | void dma_irq_handler() {
function init (line 24) | void init() {
function main (line 28) | int main() {
FILE: sw/basic-gpio/main.c
function wait (line 7) | void wait(uint32_t nOps) {
function main (line 16) | int main(int argc, char **argv) {
FILE: sw/basic-gpio/uart.c
function sendString (line 5) | int sendString(char* str, long len) {
function putChr (line 16) | void putChr(char chr) {
FILE: sw/basic-gpio/util.c
function swap (line 10) | void swap(char *x, char *y) {
FILE: sw/basic-multicore/main.c
function main (line 1) | int main(unsigned hart_id) {
FILE: sw/blocking-sleep/main.c
function irq_handler (line 24) | void irq_handler(void) {
function main (line 43) | int main() {
FILE: sw/busy-wait-sleep/main.c
function main (line 14) | int main() {
FILE: sw/c++-lib/main.cpp
type A (line 6) | struct A {
method A (line 10) | A(int a, int b) : a(a), b(b) {}
method bar (line 14) | virtual int bar() {
type B (line 19) | struct B : public A {
method foo (line 22) | virtual int foo() override {
function main (line 27) | int main() {
FILE: sw/clock-ticks/irq.c
function irq_empty_handler (line 16) | static void irq_empty_handler() {}
function level_1_interrupt_handler (line 28) | void level_1_interrupt_handler(uint32_t cause) {
function register_interrupt_handler (line 60) | void register_interrupt_handler(uint32_t irq_id, irq_handler_t fn) {
function register_timer_interrupt_handler (line 70) | void register_timer_interrupt_handler(irq_handler_t fn) {
FILE: sw/clock-ticks/main.c
function set_next_timer_interrupt (line 6) | static void set_next_timer_interrupt() {
function timer_irq_handler (line 13) | void timer_irq_handler() {
function main (line 18) | int main() {
FILE: sw/crc8/main.c
function crc8 (line 8) | unsigned char crc8(unsigned char *data, int length) {
function main (line 38) | int main(int argc, char **argv) {
FILE: sw/crc8/uart.c
function sendString (line 5) | int sendString(char* str, long len) {
function putChr (line 16) | void putChr(char chr) {
FILE: sw/crc8/util.c
function swap (line 10) | void swap(char *x, char *y) {
FILE: sw/flashTest/main.cpp
function main (line 20) | int main() {
function setTargetBlock (line 36) | void setTargetBlock(uint64_t addr) {
function readFlash (line 41) | void readFlash(char* dst, uint64_t addr, size_t len) {
function writeFlash (line 50) | void writeFlash(const char* src, uint64_t addr, size_t len) {
FILE: sw/mramTest/main.cpp
function main (line 7) | int main() {
FILE: sw/mrv32-uart/main.c
function delay (line 8) | void delay(uint32_t loops) {
function main (line 14) | int main() {
FILE: sw/mrv32-uart/platform.h
type UART_REGS (line 17) | typedef struct {
FILE: sw/mrv32-uart/uart.c
function sendString (line 5) | int sendString(char* str, long len) {
function putChr (line 16) | void putChr(char chr) {
FILE: sw/mrv32-uart/util.c
function swap (line 10) | void swap(char *x, char *y) {
FILE: sw/peripheral-in-the-loop/main.c
type BUS_BRIDGE_TYPE (line 4) | typedef uint32_t BUS_BRIDGE_TYPE;
function read_stuff (line 12) | void read_stuff() {
function write_stuff (line 22) | void write_stuff() {
function virtual_bus_irq_handler (line 35) | void virtual_bus_irq_handler() {
function main (line 42) | int main() {
FILE: sw/printf/main.c
function main (line 6) | int main(int argc, char **argv) {
FILE: sw/simple-display/libDisplay.cpp
type display (line 17) | namespace display {
function setPixel (line 19) | void setPixel(Framebuffer::Type frame, Point pixel, Color color) {
function drawLine (line 23) | void drawLine(Framebuffer::Type frame, PointF from, PointF to, Color c...
function drawRect (line 31) | void drawRect(Framebuffer::Type frame, PointF ol, PointF ur, Color col...
function fillRect (line 44) | void fillRect(Framebuffer::Type frame, PointF ol, PointF ur, Color col...
function applyFrame (line 67) | void applyFrame() {
function fillFrame (line 71) | void fillFrame(Framebuffer::Type frame, Color color) {
FILE: sw/simple-display/libDisplay.hpp
function fromRGB (line 14) | inline Framebuffer::Color fromRGB(uint8_t r, uint8_t g, uint8_t b) {
type display (line 22) | namespace display {
FILE: sw/simple-display/main.cpp
function activeWait (line 16) | void activeWait(float factor = 0.5) {
function Point (line 21) | Point getRandomPoint() {
function Color (line 25) | Color getRandomColor() {
function drawBackground (line 29) | void drawBackground() {
function drawFunnyRects (line 38) | void drawFunnyRects() {
function progressBar (line 57) | void progressBar(bool horizontal, Framebuffer::PointF base, Framebuffer:...
function drawFunnyBar (line 64) | void drawFunnyBar(bool horizontal = false) {
function main (line 99) | int main() {
FILE: sw/simple-scheduler/main.c
type state_t (line 11) | enum state_t {
type context_t (line 18) | typedef struct {
type coroutine_t (line 23) | typedef struct {
function switch_to_scheduler (line 40) | void switch_to_scheduler() {
function switch_to_coroutine (line 44) | void switch_to_coroutine(coroutine_t *cor) {
function launch_coroutine (line 50) | void launch_coroutine(coroutine_t *cor) {
function function_A (line 59) | void function_A(void *arg) {
function function_B (line 65) | void function_B(void *arg) {
function coroutine_t (line 74) | coroutine_t *create_coroutine(entrypoint_t fn, void *arg) {
function free_coroutine (line 92) | void free_coroutine(coroutine_t *cor) {
function main (line 96) | int main() {
FILE: sw/simple-scheduler/no-clib/main.c
type state_t (line 11) | enum state_t {
type context_t (line 18) | typedef struct {
type coroutine_t (line 23) | typedef struct {
function switch_to_scheduler (line 40) | void switch_to_scheduler() {
function switch_to_coroutine (line 44) | void switch_to_coroutine(coroutine_t *cor) {
function launch_coroutine (line 50) | void launch_coroutine(coroutine_t *cor) {
function function_A (line 59) | void function_A(void *arg) {
function function_B (line 65) | void function_B(void *arg) {
function coroutine_t (line 74) | coroutine_t *create_coroutine(entrypoint_t fn, void *arg) {
function free_coroutine (line 92) | void free_coroutine(coroutine_t *cor) {
function main (line 96) | int main() {
FILE: sw/simple-sensor/irq.c
function irq_empty_handler (line 16) | static void irq_empty_handler() {}
function level_1_interrupt_handler (line 28) | void level_1_interrupt_handler(uint32_t cause) {
function register_interrupt_handler (line 60) | void register_interrupt_handler(uint32_t irq_id, irq_handler_t fn) {
function register_timer_interrupt_handler (line 70) | void register_timer_interrupt_handler(irq_handler_t fn) {
FILE: sw/simple-sensor/main.c
function sensor_irq_handler (line 11) | void sensor_irq_handler() {
function dump_sensor_data (line 15) | void dump_sensor_data() {
function main (line 27) | int main() {
FILE: sw/sys-read/main.c
function main (line 3) | int main(int argc, char **argv) {
FILE: vp/src/core/common/bus_lock_if.h
type bus_lock_if (line 3) | struct bus_lock_if {
FILE: vp/src/core/common/clint.h
function update_and_get_mtime (line 75) | uint64_t update_and_get_mtime() override {
FILE: vp/src/core/common/clint_if.h
type clint_if (line 5) | struct clint_if {
FILE: vp/src/core/common/core_defs.h
type Architecture (line 3) | enum Architecture {
function CoreExecStatus (line 9) | enum class CoreExecStatus {
FILE: vp/src/core/common/debug.h
type debug_target_if (line 12) | struct debug_target_if {
FILE: vp/src/core/common/debug_memory.h
type DebugMemoryInterface (line 13) | struct DebugMemoryInterface
FILE: vp/src/core/common/dmi.h
function class (line 5) | class MemoryDMI {
function get_start (line 55) | uint64_t get_start() {
function get_end (line 59) | uint64_t get_end() {
function get_size (line 63) | uint64_t get_size() {
function contains (line 67) | bool contains(uint64_t addr) {
FILE: vp/src/core/common/elf_loader.h
type typename (line 12) | typedef typename T::addr_t addr_t;
type typename (line 13) | typedef typename T::Elf_Ehdr Elf_Ehdr;
type typename (line 14) | typedef typename T::Elf_Phdr Elf_Phdr;
type typename (line 15) | typedef typename T::Elf_Shdr Elf_Shdr;
type typename (line 16) | typedef typename T::Elf_Sym Elf_Sym;
type load_executable_exception (line 23) | struct load_executable_exception
function addr_t (line 118) | addr_t get_memory_end() {
function addr_t (line 125) | addr_t get_heap_addr() {
function addr_t (line 131) | addr_t get_entrypoint() {
function Elf_Sym (line 149) | const Elf_Sym *get_symbol(const char *symbol_name) {
function addr_t (line 169) | addr_t get_begin_signature_address() {
function addr_t (line 174) | addr_t get_end_signature_address() {
function addr_t (line 179) | addr_t get_to_host_address() {
function Elf_Shdr (line 198) | const Elf_Shdr *get_section(const char *section_name) {
FILE: vp/src/core/common/fp.h
function f32_isNegative (line 24) | inline bool f32_isNegative(float32_t x) {
function f64_isNegative (line 28) | inline bool f64_isNegative(float64_t x) {
function f32_isNaN (line 40) | inline bool f32_isNaN(float32_t x) {
function f64_isNaN (line 48) | inline bool f64_isNaN(float64_t x) {
function unbox_f32 (line 53) | struct FpRegs {
FILE: vp/src/core/common/gdb-mc/gdb_runner.h
function SC_MODULE (line 9) | SC_MODULE(GDBServerRunner) {
FILE: vp/src/core/common/gdb-mc/gdb_server.cpp
type sockaddr_in (line 69) | struct sockaddr_in
type sockaddr (line 87) | struct sockaddr
FILE: vp/src/core/common/gdb-mc/gdb_server.h
function SC_MODULE (line 24) | SC_MODULE(GDBServer) {
FILE: vp/src/core/common/gdb-mc/libgdb/include/libgdb/parser1.h
type gdb_kind_t (line 14) | typedef enum {
type gdb_packet_t (line 21) | typedef struct {
FILE: vp/src/core/common/gdb-mc/libgdb/include/libgdb/parser2.h
type LIBGDB_ADDR_TYPE (line 21) | typedef LIBGDB_ADDR_TYPE gdb_addr_t;
type gdb_thread_t (line 30) | typedef struct {
type gdb_ztype_t (line 35) | typedef enum {
type gdb_breakpoint_t (line 43) | typedef struct {
type gdb_memory_t (line 49) | typedef struct {
type gdb_memory_write_t (line 54) | typedef struct {
type gdb_cmd_h_t (line 59) | typedef struct {
type gdb_vcont_t (line 64) | typedef struct _gdb_vcont_t gdb_vcont_t;
type _gdb_vcont_t (line 66) | struct _gdb_vcont_t {
type gdb_argument_t (line 74) | typedef enum {
type gdb_command_t (line 85) | typedef struct {
FILE: vp/src/core/common/gdb-mc/libgdb/include/libgdb/response.h
type gdb_signal_t (line 10) | typedef enum {
FILE: vp/src/core/common/gdb-mc/libgdb/parser1.c
function mpc_val_t (line 10) | static mpc_val_t *
function mpc_val_t (line 44) | static mpc_val_t *
function mpc_parser_t (line 70) | static mpc_parser_t *
function mpc_parser_t (line 79) | static mpc_parser_t *
function mpc_parser_t (line 89) | static mpc_parser_t *
function mpc_parser_t (line 99) | static mpc_parser_t *
function mpc_parser_t (line 105) | static mpc_parser_t *
function gdb_packet_t (line 113) | gdb_packet_t *
FILE: vp/src/core/common/gdb-mc/libgdb/parser2.c
function mpc_val_t (line 12) | static mpc_val_t *
function mpc_val_t (line 28) | static mpc_val_t *
function mpc_parser_t (line 43) | static mpc_parser_t *
function mpc_val_t (line 49) | static mpc_val_t *
function mpc_parser_t (line 64) | static mpc_parser_t *
function mpc_val_t (line 70) | static mpc_val_t *
function mpc_val_t (line 83) | static mpc_val_t *
function mpc_parser_t (line 102) | static mpc_parser_t *
function mpc_val_t (line 110) | static mpc_val_t *
function mpc_parser_t (line 134) | static mpc_parser_t *
function mpc_parser_t (line 144) | static mpc_parser_t *
function mpc_parser_t (line 158) | static mpc_parser_t *
function mpc_parser_t (line 171) | static mpc_parser_t *
function mpc_val_t (line 177) | static mpc_val_t *
function mpc_val_t (line 214) | static mpc_val_t *
function mpc_parser_t (line 231) | static mpc_parser_t *
function mpc_parser_t (line 251) | static mpc_parser_t *
function mpc_parser_t (line 259) | static mpc_parser_t *
function mpc_parser_t (line 267) | static mpc_parser_t *
function mpc_parser_t (line 275) | static mpc_parser_t *
function mpc_parser_t (line 292) | static mpc_parser_t *
function mpc_parser_t (line 299) | static mpc_parser_t *
function mpc_parser_t (line 305) | static mpc_parser_t *
function mpc_parser_t (line 311) | static mpc_parser_t *
function gdb_command_t (line 325) | gdb_command_t *
FILE: vp/src/core/common/gdb-mc/libgdb/response.c
function kind_to_char (line 12) | static char
FILE: vp/src/core/common/gdb-mc/libgdb/util.c
function calc_csum (line 21) | int
function gdb_is_valid (line 112) | bool
function gdb_command_t (line 129) | gdb_command_t *
function gdb_free_cmd (line 141) | void
function gdb_free_packet (line 195) | void
FILE: vp/src/core/common/gdb-mc/register_format.h
function class (line 10) | class RegisterFormater {
FILE: vp/src/core/common/instr.cpp
type Compressed (line 351) | namespace Compressed {
type Opcode (line 352) | enum Opcode {
function C_ADDI4SPN_NZUIMM (line 778) | unsigned C_ADDI4SPN_NZUIMM(uint32_t n) {
function C_LW_UIMM (line 783) | unsigned C_LW_UIMM(uint32_t n) {
function C_LD_UIMM (line 787) | unsigned C_LD_UIMM(uint32_t n) {
function C_SW_UIMM (line 791) | unsigned C_SW_UIMM(uint32_t n) {
function C_SD_UIMM (line 795) | unsigned C_SD_UIMM(uint32_t n) {
function C_JAL_IMM (line 799) | int32_t C_JAL_IMM(int32_t n) {
function C_ADDI16SP_NZIMM (line 805) | int32_t C_ADDI16SP_NZIMM(int32_t n) {
function C_LUI_NZIMM (line 810) | int32_t C_LUI_NZIMM(int32_t n) {
function C_J_IMM (line 814) | int32_t C_J_IMM(int32_t n) {
function C_BRANCH_IMM (line 818) | int32_t C_BRANCH_IMM(int32_t n) {
function C_LWSP_UIMM (line 823) | uint32_t C_LWSP_UIMM(uint32_t n) {
function C_SWSP_UIMM (line 827) | uint32_t C_SWSP_UIMM(uint32_t n) {
function C_LDSP_UIMM (line 831) | uint32_t C_LDSP_UIMM(uint32_t n) {
function C_SDSP_UIMM (line 835) | uint32_t C_SDSP_UIMM(uint32_t n) {
type InstructionFactory (line 839) | struct InstructionFactory {
method T (line 842) | static T ADD(unsigned rd, unsigned rs1, unsigned rs2) {
method T (line 846) | static T AND(unsigned rd, unsigned rs1, unsigned rs2) {
method T (line 850) | static T OR(unsigned rd, unsigned rs1, unsigned rs2) {
method T (line 854) | static T XOR(unsigned rd, unsigned rs1, unsigned rs2) {
method T (line 858) | static T SUB(unsigned rd, unsigned rs1, unsigned rs2) {
method T (line 862) | static T LW(unsigned rd, unsigned rs1, int I_imm) {
method T (line 866) | static T LD(unsigned rd, unsigned rs1, int I_imm) {
method T (line 870) | static T FLW(unsigned rd, unsigned rs1, int I_imm) {
method T (line 874) | static T FLD(unsigned rd, unsigned rs1, int I_imm) {
method T (line 878) | static T SW(unsigned rs1, unsigned rs2, int S_imm) {
method T (line 883) | static T SD(unsigned rs1, unsigned rs2, int S_imm) {
method T (line 888) | static T FSW(unsigned rs1, unsigned rs2, int S_imm) {
method T (line 893) | static T FSD(unsigned rs1, unsigned rs2, int S_imm) {
method T (line 898) | static T LUI(unsigned rd, int U_imm) {
method T (line 902) | static T ADDI(unsigned rd, unsigned rs1, int I_imm) {
method T (line 906) | static T ANDI(unsigned rd, unsigned rs1, int I_imm) {
method T (line 910) | static T SRLI(unsigned rd, unsigned rs1, unsigned shamt) {
method T (line 914) | static T SRAI(unsigned rd, unsigned rs1, unsigned shamt) {
method T (line 918) | static T SLLI(unsigned rd, unsigned rs1, unsigned shamt) {
method T (line 922) | static T JAL(unsigned rd, int J_imm) {
method T (line 928) | static T JALR(unsigned rd, unsigned rs1, int I_imm) {
method T (line 932) | static T BEQ(unsigned rs1, unsigned rs2, int B_imm) {
method T (line 938) | static T BNE(unsigned rs1, unsigned rs2, int B_imm) {
method T (line 944) | static T EBREAK() {
method T (line 948) | static T ADDIW(unsigned rd, unsigned rs1, int I_imm) {
method T (line 952) | static T ADDW(unsigned rd, unsigned rs1, unsigned rs2) {
method T (line 956) | static T SUBW(unsigned rd, unsigned rs1, unsigned rs2) {
function decode_compressed (line 961) | Compressed::Opcode decode_compressed(Instruction &instr, Architecture ar...
function expand_compressed (line 1129) | Opcode::Mapping expand_compressed(Instruction &instr, Compressed::Opcode...
FILE: vp/src/core/common/instr.h
type Parts (line 12) | enum Parts {
type Mapping (line 234) | enum Mapping {
function Type (line 428) | enum class Type {
FILE: vp/src/core/common/irq_if.h
type PrivilegeLevel (line 6) | typedef uint32_t PrivilegeLevel;
type external_interrupt_target (line 14) | struct external_interrupt_target {
type clint_interrupt_target (line 21) | struct clint_interrupt_target {
type interrupt_gateway (line 28) | struct interrupt_gateway {
FILE: vp/src/core/common/load_if.h
function class (line 7) | class load_if {
FILE: vp/src/core/common/mmu.h
function R (line 20) | struct pte_t {
function W (line 29) | bool W() {
function X (line 32) | bool X() {
function U (line 35) | bool U() {
function G (line 38) | bool G() {
function A (line 41) | bool A() {
function D (line 44) | bool D() {
function operator (line 48) | operator uint64_t() {
type vm_info (line 53) | struct vm_info {
type tlb_entry_t (line 70) | struct tlb_entry_t {
function flush_tlb (line 86) | void flush_tlb() {
function translate_virtual_to_physical_addr (line 90) | uint64_t translate_virtual_to_physical_addr(uint64_t vaddr, MemoryAccess...
function vm_info (line 125) | vm_info decode_vm_info(PrivilegeLevel prv) {
function check_vaddr_extension (line 145) | bool check_vaddr_extension(uint64_t vaddr, const vm_info &vm) {
function walk (line 154) | uint64_t walk(uint64_t vaddr, MemoryAccessType type, PrivilegeLevel mode) {
FILE: vp/src/core/common/mmu_mem_if.h
type MemoryAccessType (line 6) | enum MemoryAccessType { FETCH, LOAD, STORE }
type mmu_memory_if (line 8) | struct mmu_memory_if {
FILE: vp/src/core/common/rawmode.cpp
type termios (line 43) | struct termios
function reset_term (line 45) | static void reset_term(void) {
function sighandler (line 53) | static void sighandler(int num) {
function sethandler (line 59) | static void sethandler(void) {
function enableRawMode (line 79) | void enableRawMode(int fd) {
function disableRawMode (line 118) | void disableRawMode(int fd) {
FILE: vp/src/core/common/real_clint.cpp
function timercb (line 24) | static void
FILE: vp/src/core/common/real_clint.h
type Timer (line 35) | typedef Timer::usecs usecs;
FILE: vp/src/core/common/timer.cpp
function xnanosleep (line 17) | static int
type timespec (line 31) | struct timespec
type sigaction (line 80) | struct sigaction
FILE: vp/src/core/common/timer.h
function class (line 11) | class Timer {
FILE: vp/src/core/common/trap.h
type ExceptionCode (line 3) | enum ExceptionCode {
type SimulationTrap (line 36) | struct SimulationTrap {
function raise_trap (line 41) | inline void raise_trap(ExceptionCode exc, unsigned long mtval) {
FILE: vp/src/core/rv32/csr.h
function namespace (line 12) | namespace rv32 {
type csr_mvendorid (line 88) | struct csr_mvendorid {
type csr_mstatus (line 98) | struct csr_mstatus {
function Mode (line 127) | struct csr_mtvec {
type csr_mie (line 149) | struct csr_mie {
type csr_mip (line 173) | struct csr_mip {
type csr_mepc (line 197) | struct csr_mepc {
type csr_mcause (line 203) | struct csr_mcause {
type csr_mcounteren (line 213) | struct csr_mcounteren {
type csr_mcountinhibit (line 225) | struct csr_mcountinhibit {
type csr_pmpcfg (line 237) | struct csr_pmpcfg {
type csr_satp (line 252) | struct csr_satp {
type csr_fcsr (line 263) | struct csr_fcsr {
type csr_64 (line 287) | struct csr_64 {
function namespace (line 301) | namespace csr {
function is_valid_csr32_addr (line 586) | struct csr_table {
function default_write32 (line 701) | void default_write32(unsigned addr, uint32_t value) {
function default_read32 (line 707) | uint32_t default_read32(unsigned addr) {
FILE: vp/src/core/rv32/elf_loader.h
type Elf32_Half (line 9) | typedef uint16_t Elf32_Half;
type Elf32_Off (line 10) | typedef uint32_t Elf32_Off;
type Elf32_Addr (line 11) | typedef uint32_t Elf32_Addr;
type Elf32_Word (line 12) | typedef uint32_t Elf32_Word;
type Elf32_Sword (line 13) | typedef int32_t Elf32_Sword;
type Elf32_Ehdr (line 17) | typedef struct {
type Elf32_Phdr (line 34) | typedef struct {
type Elf32_Shdr (line 45) | typedef struct {
type Elf32_Sym (line 58) | typedef struct {
type Elf32_PhdrType (line 67) | enum Elf32_PhdrType { PT_NULL = 0, PT_LOAD = 1, PT_DYNAMIC = 2, PT_INTER...
type GenericElfLoader (line 78) | typedef GenericElfLoader<Elf32Types> ELFLoader;
FILE: vp/src/core/rv32/iss.cpp
function CoreExecStatus (line 1469) | CoreExecStatus ISS::get_status(void) {
function PrivilegeLevel (line 1630) | PrivilegeLevel ISS::prepare_trap(SimulationTrap &e) {
function PendingInterrupts (line 1711) | PendingInterrupts ISS::compute_pending_interrupts() {
FILE: vp/src/core/rv32/iss.h
function namespace (line 31) | namespace rv32 {
function m_mode (line 289) | inline bool m_mode() {
function s_mode (line 293) | inline bool s_mode() {
function u_mode (line 297) | inline bool u_mode() {
function has_pending_enabled_interrupts (line 307) | bool has_pending_enabled_interrupts() {
function has_local_pending_enabled_interrupts (line 311) | bool has_local_pending_enabled_interrupts() {
type DirectCoreRunner (line 330) | struct DirectCoreRunner
FILE: vp/src/core/rv32/mem.h
function namespace (line 7) | namespace rv32 {
FILE: vp/src/core/rv32/mem_if.h
function namespace (line 5) | namespace rv32 {
FILE: vp/src/core/rv32/mmu.h
function namespace (line 6) | namespace rv32 {
FILE: vp/src/core/rv32/syscall.cpp
type rv32_timeval (line 23) | struct rv32_timeval {
type rv32_timespec (line 28) | struct rv32_timespec {
type rv32_stat (line 33) | struct rv32_stat {
function _copy_timespec (line 52) | void _copy_timespec(rv32_timespec *dst, timespec *src) {
function sys_fstat (line 57) | int sys_fstat(SyscallHandler *sys, int fd, rv32_stat *s_addr) {
function sys_gettimeofday (line 79) | int sys_gettimeofday(SyscallHandler *sys, rv32_timeval *tp, void *tzp) {
function sys_time (line 95) | int sys_time(SyscallHandler *sys, rv32_time_t *tloc) {
type rv_sc (line 108) | namespace rv_sc {
function translateRVFlagsToHost (line 118) | int translateRVFlagsToHost(const int flags) {
function sys_brk (line 134) | int sys_brk(SyscallHandler *sys, void *addr) {
function sys_write (line 151) | int sys_write(SyscallHandler *sys, int fd, const void *buf, size_t count) {
function sys_read (line 166) | int sys_read(SyscallHandler *sys, int fd, void *buf, size_t count) {
function sys_lseek (line 176) | int sys_lseek(int fd, off_t offset, int whence) {
function sys_open (line 182) | int sys_open(SyscallHandler *sys, const char *pathname, int flags, mode_...
function sys_close (line 193) | int sys_close(int fd) {
type rv32_timeval (line 215) | struct rv32_timeval
FILE: vp/src/core/rv32/syscall.h
function namespace (line 66) | namespace rv32 {
FILE: vp/src/core/rv32/syscall_if.h
function namespace (line 5) | namespace rv32 {
FILE: vp/src/core/rv32/timing/timing_external.h
type SimTimingInterface (line 14) | struct SimTimingInterface {
function timing_if (line 21) | struct ExternalTimingDecorator : public timing_if {
FILE: vp/src/core/rv32/timing/timing_simple.h
function timing_if (line 5) | struct SimpleTimingDecorator : public timing_if {
FILE: vp/src/core/rv64/csr.h
function namespace (line 12) | namespace rv64 {
type csr_mvendorid (line 72) | struct csr_mvendorid {
function Mode (line 121) | struct csr_mtvec {
type csr_mie (line 143) | struct csr_mie {
type csr_mip (line 167) | struct csr_mip {
type csr_mepc (line 191) | struct csr_mepc {
type csr_mcause (line 197) | struct csr_mcause {
type csr_mcounteren (line 207) | struct csr_mcounteren {
type csr_mcountinhibit (line 219) | struct csr_mcountinhibit {
type csr_pmpcfg (line 231) | struct csr_pmpcfg {
type csr_pmpaddr (line 237) | struct csr_pmpaddr {
type csr_satp (line 251) | struct csr_satp {
type csr_fcsr (line 263) | struct csr_fcsr {
function namespace (line 282) | namespace csr {
function is_valid_csr64_addr (line 555) | struct csr_table {
function default_write64 (line 664) | void default_write64(unsigned addr, uint64_t value) {
function default_read64 (line 670) | uint64_t default_read64(unsigned addr) {
FILE: vp/src/core/rv64/elf_loader.h
type Elf64_Addr (line 9) | typedef uint64_t Elf64_Addr;
type Elf64_Off (line 10) | typedef uint64_t Elf64_Off;
type Elf64_Half (line 11) | typedef uint16_t Elf64_Half;
type Elf64_Word (line 12) | typedef uint32_t Elf64_Word;
type Elf64_Sword (line 13) | typedef int32_t Elf64_Sword;
type Elf64_Xword (line 14) | typedef uint64_t Elf64_Xword;
type Elf64_Sxword (line 15) | typedef int64_t Elf64_Sxword;
type Elf64_Ehdr (line 19) | typedef struct {
type Elf64_Shdr (line 36) | typedef struct {
type Elf64_Sym (line 49) | typedef struct {
type Elf64_Phdr (line 58) | typedef struct {
type Elf64_PhdrType (line 69) | enum Elf64_PhdrType { PT_NULL = 0, PT_LOAD = 1, PT_DYNAMIC = 2, PT_INTER...
type GenericElfLoader (line 80) | typedef GenericElfLoader<Elf64Types> ELFLoader;
FILE: vp/src/core/rv64/iss.cpp
function CoreExecStatus (line 1529) | CoreExecStatus ISS::get_status(void) {
function PrivilegeLevel (line 1689) | PrivilegeLevel ISS::prepare_trap(SimulationTrap &e) {
function PendingInterrupts (line 1770) | PendingInterrupts ISS::compute_pending_interrupts() {
FILE: vp/src/core/rv64/iss.h
function namespace (line 32) | namespace rv64 {
function execute_amo_d (line 278) | inline void execute_amo_d(Instruction &instr, std::function<int64_t(int6...
function m_mode (line 294) | inline bool m_mode() {
function s_mode (line 298) | inline bool s_mode() {
function u_mode (line 302) | inline bool u_mode() {
function has_pending_enabled_interrupts (line 312) | bool has_pending_enabled_interrupts() {
function has_local_pending_enabled_interrupts (line 316) | bool has_local_pending_enabled_interrupts() {
type DirectCoreRunner (line 335) | struct DirectCoreRunner
FILE: vp/src/core/rv64/mem.h
function namespace (line 7) | namespace rv64 {
FILE: vp/src/core/rv64/mem_if.h
function namespace (line 5) | namespace rv64 {
FILE: vp/src/core/rv64/mmu.h
function namespace (line 6) | namespace rv64 {
FILE: vp/src/core/rv64/syscall.cpp
type rv64_timeval (line 23) | struct rv64_timeval {
type rv64_timespec (line 28) | struct rv64_timespec {
type rv64_stat (line 33) | struct rv64_stat {
function _copy_timespec (line 52) | void _copy_timespec(rv64_timespec *dst, timespec *src) {
function sys_fstat (line 57) | int sys_fstat(SyscallHandler *sys, int fd, rv64_stat *s_addr) {
function sys_gettimeofday (line 79) | int sys_gettimeofday(SyscallHandler *sys, rv64_timeval *tp, void *tzp) {
function sys_time (line 95) | int sys_time(SyscallHandler *sys, rv64_time_t *tloc) {
type rv_sc (line 108) | namespace rv_sc {
function translateRVFlagsToHost (line 118) | int translateRVFlagsToHost(const int flags) {
function sys_brk (line 134) | int sys_brk(SyscallHandler *sys, void *addr) {
function sys_write (line 151) | int sys_write(SyscallHandler *sys, int fd, const void *buf, size_t count) {
function sys_read (line 166) | int sys_read(SyscallHandler *sys, int fd, void *buf, size_t count) {
function sys_lseek (line 176) | int sys_lseek(int fd, off_t offset, int whence) {
function sys_open (line 182) | int sys_open(SyscallHandler *sys, const char *pathname, int flags, mode_...
function sys_close (line 193) | int sys_close(int fd) {
FILE: vp/src/core/rv64/syscall.h
function namespace (line 64) | namespace rv64 {
FILE: vp/src/core/rv64/syscall_if.h
function namespace (line 5) | namespace rv64 {
FILE: vp/src/platform/basic/basic_timer.h
type BasicTimer (line 10) | struct BasicTimer
function run (line 20) | void run() {
FILE: vp/src/platform/basic/display.hpp
type Display (line 18) | struct Display : public sc_core::sc_module {
FILE: vp/src/platform/basic/dma.h
type SimpleDMA (line 12) | struct SimpleDMA
function _copy_block (line 63) | void _copy_block(uint32_t off, uint32_t n) {
function _perform_memcpy (line 68) | void _perform_memcpy() {
function run (line 81) | void run() {
function transport (line 117) | void transport(tlm::tlm_generic_payload &trans, sc_core::sc_time &delay) {
function do_transaction (line 145) | void do_transaction(tlm::tlm_command cmd, uint64_t addr, uint8_t *data, ...
FILE: vp/src/platform/basic/ethernet.cpp
function printHex (line 33) | void printHex(const unsigned char *buf, const uint32_t len) {
function printDec (line 39) | void printDec(const unsigned char *buf, const uint32_t len) {
function dump_ethernet_frame (line 45) | void dump_ethernet_frame(uint8_t *buf, size_t size, bool verbose = false) {
type ifreq (line 204) | struct ifreq
type ifreq (line 226) | struct ifreq
type ifreq (line 227) | struct ifreq
type ether_header (line 251) | struct ether_header
type ether_header (line 251) | struct ether_header
FILE: vp/src/platform/basic/ethernet.h
type arp_eth_header (line 20) | struct arp_eth_header {
type EthernetDevice (line 32) | struct EthernetDevice
function register_access_callback (line 88) | void register_access_callback(const vp::map::register_access_t &r) {
function transport (line 108) | void transport(tlm::tlm_generic_payload &trans, sc_core::sc_time &delay) {
function run (line 112) | void run() {
FILE: vp/src/platform/basic/flash.h
function setPos (line 29) | void setPos(uint64_t blockOffset) {
function setData (line 39) | void setData(const uint8_t* source, uint16_t pos, uint16_t length) {
function getData (line 44) | void getData(uint8_t* target, uint16_t pos, uint16_t length) {
function writeBlock (line 49) | void writeBlock(uint64_t blockOffset) {
function readBlock (line 61) | void readBlock(uint64_t blockOffset) {
function clear (line 72) | void clear() {
type Flashcontroller (line 80) | struct Flashcontroller
function transport (line 139) | void transport(tlm::tlm_generic_payload& trans, sc_core::sc_time& delay) {
FILE: vp/src/platform/basic/main.cpp
class BasicOptions (line 36) | class BasicOptions : public Options {
method BasicOptions (line 80) | BasicOptions(void) {
method printValues (line 96) | void printValues(std::ostream& os) const override {
method parse (line 103) | void parse(int argc, char **argv) override {
function sc_main (line 116) | int sc_main(int argc, char **argv) {
FILE: vp/src/platform/basic/random_source.h
type RandomSource (line 10) | struct RandomSource
function transport (line 17) | void transport(tlm::tlm_generic_payload &trans, sc_core::sc_time &delay) {
FILE: vp/src/platform/basic/sensor.h
type SimpleSensor (line 13) | struct SimpleSensor
function transport (line 45) | void transport(tlm::tlm_generic_payload &trans, sc_core::sc_time &delay) {
FILE: vp/src/platform/basic/sensor2.h
type SimpleSensor2 (line 15) | struct SimpleSensor2
function data_frame_access_callback (line 53) | void data_frame_access_callback(tlm::tlm_generic_payload &trans, sc_core...
function register_access_callback (line 58) | void register_access_callback(const vp::map::register_access_t &r) {
function transport (line 75) | void transport(tlm::tlm_generic_payload &trans, sc_core::sc_time &delay) {
FILE: vp/src/platform/common/async_event.h
function class (line 30) | class AsyncEvent : public sc_core::sc_prim_channel {
FILE: vp/src/platform/common/bus.h
function contains (line 12) | struct PortMapping {
function global_to_local (line 24) | uint64_t global_to_local(uint64_t addr) {
FILE: vp/src/platform/common/fd_abstract_uart.h
function class (line 12) | class FD_ABSTRACT_UART : public UART_IF {
FILE: vp/src/platform/common/fe310_plic.h
function gateway_trigger_interrupt (line 106) | void gateway_trigger_interrupt(uint32_t irq_id) {
function clear_pending_interrupt (line 120) | void clear_pending_interrupt(unsigned irq_id) {
function hart_get_next_pending_interrupt (line 130) | unsigned hart_get_next_pending_interrupt(unsigned hart_id, bool consider...
function transport (line 157) | void transport(tlm::tlm_generic_payload &trans, sc_core::sc_time &delay) {
function post_write_interrupt_priorities (line 163) | void post_write_interrupt_priorities(RegisterRange::WriteInfo) {
function hart_has_pending_enabled_interrupts (line 214) | bool hart_has_pending_enabled_interrupts(unsigned hart_id) {
function run (line 218) | void run() {
FILE: vp/src/platform/common/fu540_plic.cpp
function GET_IDX (line 13) | inline uint32_t GET_IDX(uint32_t& irq) { return irq / 32; }
function GET_OFF (line 14) | inline uint32_t GET_OFF(uint32_t& irq) { return 1 << irq % 32; }
function assert_addr (line 21) | static void assert_addr(size_t start, size_t end, RegisterRange *range) {
FILE: vp/src/platform/common/fu540_plic.h
type FU540_PLIC (line 10) | struct FU540_PLIC
type std (line 49) | typedef std::map<unsigned int, HartConfig*> hartmap;
FILE: vp/src/platform/common/memory.h
type SimpleMemory (line 14) | struct SimpleMemory
function load_data (line 32) | void load_data(const char *src, uint64_t dst_addr, size_t n) override {
function load_zero (line 37) | void load_zero(uint64_t dst_addr, size_t n) override {
function load_binary_file (line 42) | void load_binary_file(const std::string &filename, unsigned addr) {
function write_data (line 48) | void write_data(unsigned addr, const uint8_t *src, unsigned num_bytes) {
function read_data (line 54) | void read_data(unsigned addr, uint8_t *dst, unsigned num_bytes) {
function transport (line 60) | void transport(tlm::tlm_generic_payload &trans, sc_core::sc_time &delay) {
function transport_dbg (line 65) | unsigned transport_dbg(tlm::tlm_generic_payload &trans) {
function get_direct_mem_ptr (line 84) | bool get_direct_mem_ptr(tlm::tlm_generic_payload &trans, tlm::tlm_dmi &d...
FILE: vp/src/platform/common/memory_mapped_file.h
type MemoryMappedFile (line 17) | struct MemoryMappedFile
function write_data (line 45) | void write_data(unsigned addr, uint8_t *src, unsigned num_bytes) {
function read_data (line 54) | void read_data(unsigned addr, uint8_t *dst, unsigned num_bytes) {
function transport (line 63) | void transport(tlm::tlm_generic_payload &trans, sc_core::sc_time &delay) {
FILE: vp/src/platform/common/options.h
function class (line 7) | class Options : public boost::program_options::options_description {
FILE: vp/src/platform/common/slip.cpp
type ifreq (line 33) | struct ifreq
type ifreq (line 75) | struct ifreq
FILE: vp/src/platform/common/slip.h
function class (line 8) | class SLIP : public FD_ABSTRACT_UART {
FILE: vp/src/platform/common/terminal.h
type SimpleTerminal (line 7) | struct SimpleTerminal
function transport (line 14) | void transport(tlm::tlm_generic_payload &trans, sc_core::sc_time &delay) {
FILE: vp/src/platform/common/uart.h
function class (line 8) | class UART : public FD_ABSTRACT_UART {
FILE: vp/src/platform/common/uart16550.h
type UART16550 (line 12) | struct UART16550
type termios (line 29) | struct termios
type termios (line 37) | struct termios
function try_receive_char (line 49) | void try_receive_char() {
function take_next_char (line 58) | uint8_t take_next_char() {
function pre_read_regs (line 68) | bool pre_read_regs(RegisterRange::ReadInfo t) {
function post_write_regs (line 82) | void post_write_regs(RegisterRange::WriteInfo t) {
function transport (line 95) | void transport(tlm::tlm_generic_payload &trans, sc_core::sc_time &delay) {
FILE: vp/src/platform/common/uart_if.h
function class (line 19) | class UART_IF : public sc_core::sc_module {
FILE: vp/src/platform/common/util.h
type BlankDevice (line 9) | struct BlankDevice
function transport (line 24) | void transport(tlm::tlm_generic_payload &trans, sc_core::sc_time &delay) {
type ZeroDevice (line 41) | struct ZeroDevice
function transport (line 48) | void transport(tlm::tlm_generic_payload &trans, sc_core::sc_time &delay) {
type SimpleUART (line 59) | struct SimpleUART
function transport (line 66) | void transport(tlm::tlm_generic_payload &trans, sc_core::sc_time &delay) {
FILE: vp/src/platform/hifive/aon.h
type AON (line 11) | struct AON
function register_access_callback (line 149) | void register_access_callback(const vp::map::register_access_t &r) {
function transport (line 153) | void transport(tlm::tlm_generic_payload &trans, sc_core::sc_time &delay) {
FILE: vp/src/platform/hifive/can.cpp
type ifreq (line 25) | struct ifreq
type sockaddr (line 36) | struct sockaddr
type ModReg (line 294) | struct ModReg {
method ModReg (line 300) | ModReg() : state(_address), address(0), mask(0), data(0){}
type LoadTX (line 329) | struct LoadTX {
type can_frame (line 370) | struct can_frame
type can_frame (line 372) | struct can_frame
type can_frame (line 380) | struct can_frame
type can_frame (line 438) | struct can_frame
type can_frame (line 460) | struct can_frame
type can_frame (line 462) | struct can_frame
type can_frame (line 470) | struct can_frame
FILE: vp/src/platform/hifive/can.h
function class (line 12) | class CAN {
FILE: vp/src/platform/hifive/can/cantest.cpp
function main (line 21) | int main(int argc, char* argv[]) {
FILE: vp/src/platform/hifive/gpio.cpp
function Pinstate (line 6) | static Pinstate getIOF(PinNumber pin, bool iofsel) {
function PinNumber (line 43) | static PinNumber getPinOffsFromSPIcs(PinNumber cs) {
function UartTXFunction (line 316) | UartTXFunction GPIO::getUartTransmitFunction(const gpio::PinNumber tx){
function SpiWriteFunction (line 324) | SpiWriteFunction GPIO::getSPIwriteFunction(gpio::PinNumber cs) {
FILE: vp/src/platform/hifive/gpio.h
type GPIO (line 14) | struct GPIO
FILE: vp/src/platform/hifive/hifive_main.cpp
class HifiveOptions (line 50) | class HifiveOptions : public Options {
method HifiveOptions (line 92) | HifiveOptions(void) {
method printValues (line 104) | void printValues(std::ostream& os) const override {
function sc_main (line 114) | int sc_main(int argc, char **argv) {
FILE: vp/src/platform/hifive/maskROM.h
type MaskROM (line 12) | struct MaskROM
function transport (line 29) | void transport(tlm::tlm_generic_payload &trans, sc_core::sc_time &delay) {
FILE: vp/src/platform/hifive/oled/common.cpp
type ss1106 (line 13) | namespace ss1106
function State (line 18) | State* getSharedState()
FILE: vp/src/platform/hifive/oled/common.hpp
type ss1106 (line 12) | namespace ss1106
type State (line 21) | struct State
FILE: vp/src/platform/hifive/oled/oled.hpp
class SS1106 (line 16) | class SS1106 {
type Command (line 23) | struct Command
type Mode (line 29) | enum class Mode : uint_fast8_t
FILE: vp/src/platform/hifive/otp.h
type OTP (line 10) | struct OTP
function transport (line 17) | void transport(tlm::tlm_generic_payload &trans, sc_core::sc_time &delay) {
FILE: vp/src/platform/hifive/prci.h
type PRCI (line 11) | struct PRCI
function register_access_callback (line 42) | void register_access_callback(const vp::map::register_access_t &r) {
function transport (line 56) | void transport(tlm::tlm_generic_payload &trans, sc_core::sc_time &delay) {
FILE: vp/src/platform/hifive/spi.h
type std (line 14) | typedef std::function<uint8_t(uint8_t)> SpiWriteFunction;
type Pin (line 16) | typedef uint32_t Pin;
type SPI (line 18) | struct SPI
function register_access_callback (line 94) | void register_access_callback(const vp::map::register_access_t &r) {
function transport (line 137) | void transport(tlm::tlm_generic_payload &trans, sc_core::sc_time &delay) {
function connect (line 141) | void connect(Pin cs, SpiWriteFunction interface) {
FILE: vp/src/platform/hifive/tunnel-uart.hpp
class Tunnel_UART (line 13) | class Tunnel_UART : public UART_IF {
FILE: vp/src/platform/hwitl/main.cpp
class HwitlOptions (line 32) | class HwitlOptions : public Options {
method HwitlOptions (line 58) | HwitlOptions(void) {
method parse (line 72) | void parse(int argc, char **argv) override {
function sc_main (line 85) | int sc_main(int argc, char **argv) {
FILE: vp/src/platform/hwitl/virtual_bus_tlm_connector.hpp
type VirtualBusMember (line 16) | struct VirtualBusMember : public sc_core::sc_module {
FILE: vp/src/platform/linux/linux_main.cpp
type LinuxOptions (line 38) | struct LinuxOptions : public Options {
method LinuxOptions (line 65) | LinuxOptions(void) {
method parse (line 76) | void parse(int argc, char **argv) override {
class Core (line 83) | class Core {
method Core (line 90) | Core(unsigned int id, MemoryDMI dmi)
method init (line 95) | void init(bool use_data_dmi, bool use_instr_dmi, clint_if *clint, uint...
method instr_memory_if (line 103) | instr_memory_if *get_instr_memory_if(bool use_instr_dmi) {
function sc_main (line 111) | int sc_main(int argc, char **argv) {
FILE: vp/src/platform/linux/prci.h
type PRCI (line 11) | struct PRCI
function register_access_callback (line 57) | void register_access_callback(const vp::map::register_access_t &r) {
function transport (line 63) | void transport(tlm::tlm_generic_payload &trans, sc_core::sc_time &delay) {
FILE: vp/src/platform/linux32/linux32_main.cpp
type LinuxOptions (line 38) | struct LinuxOptions : public Options {
method LinuxOptions (line 65) | LinuxOptions(void) {
method parse (line 76) | void parse(int argc, char **argv) override {
class Core (line 83) | class Core {
method Core (line 90) | Core(unsigned int id, MemoryDMI dmi)
method init (line 95) | void init(bool use_data_dmi, bool use_instr_dmi, clint_if *clint, uint...
method instr_memory_if (line 103) | instr_memory_if *get_instr_memory_if(bool use_instr_dmi) {
function sc_main (line 111) | int sc_main(int argc, char **argv) {
FILE: vp/src/platform/linux32/prci.h
type PRCI (line 11) | struct PRCI
function register_access_callback (line 57) | void register_access_callback(const vp::map::register_access_t &r) {
function transport (line 63) | void transport(tlm::tlm_generic_payload &trans, sc_core::sc_time &delay) {
FILE: vp/src/platform/microrv32/main.cpp
class BasicOptions (line 28) | class BasicOptions : public Options {
method BasicOptions (line 51) | BasicOptions(void) {
method parse (line 59) | void parse(int argc, char **argv) override {
function sc_main (line 66) | int sc_main(int argc, char **argv) {
FILE: vp/src/platform/microrv32/microrv32_gpio.h
type MicroRV32GPIO (line 10) | struct MicroRV32GPIO
function transport (line 25) | void transport(tlm::tlm_generic_payload &trans, sc_core::sc_time &delay) {
FILE: vp/src/platform/microrv32/microrv32_led.h
type MicroRV32LED (line 10) | struct MicroRV32LED
function transport (line 22) | void transport(tlm::tlm_generic_payload &trans, sc_core::sc_time &delay) {
FILE: vp/src/platform/microrv32/microrv32_uart.h
type MicroRV32UART (line 11) | struct MicroRV32UART
function transport (line 29) | void transport(tlm::tlm_generic_payload &trans, sc_core::sc_time &delay) {
function run (line 67) | void run() {
FILE: vp/src/platform/test32/htif.h
type HTIF (line 5) | struct HTIF
function run (line 20) | void run() {
FILE: vp/src/platform/test32/test32_main.cpp
class TestOptions (line 27) | class TestOptions : public Options {
method TestOptions (line 46) | TestOptions(void) {
method parse (line 58) | void parse(int argc, char **argv) override {
function dump_test_signature (line 64) | void dump_test_signature(TestOptions &opt, uint8_t *mem, ELFLoader &load...
function sc_main (line 94) | int sc_main(int argc, char **argv) {
FILE: vp/src/platform/tiny32-mc/mc_main.cpp
type TinyOptions (line 23) | struct TinyOptions : public Options {
method TinyOptions (line 39) | TinyOptions(void) {
method parse (line 49) | void parse(int argc, char **argv) override {
function sc_main (line 55) | int sc_main(int argc, char **argv) {
FILE: vp/src/platform/tiny32/tiny32_main.cpp
type TinyOptions (line 24) | struct TinyOptions : public Options {
method TinyOptions (line 40) | TinyOptions(void) {
method parse (line 50) | void parse(int argc, char **argv) override {
function sc_main (line 56) | int sc_main(int argc, char **argv) {
FILE: vp/src/platform/tiny64-mc/mc_main.cpp
type TinyOptions (line 23) | struct TinyOptions : public Options {
method TinyOptions (line 39) | TinyOptions(void) {
method parse (line 49) | void parse(int argc, char **argv) override {
function sc_main (line 55) | int sc_main(int argc, char **argv) {
FILE: vp/src/platform/tiny64/tiny64_main.cpp
type TinyOptions (line 25) | struct TinyOptions : public Options {
method TinyOptions (line 41) | TinyOptions(void) {
method parse (line 51) | void parse(int argc, char **argv) override {
function sc_main (line 57) | int sc_main(int argc, char **argv) {
FILE: vp/src/util/common.h
function ensure (line 10) | inline void ensure(bool cond) {
function ensure (line 15) | inline void ensure(bool cond, const std::string &reason) {
function rv64_align_address (line 20) | inline uint64_t rv64_align_address(uint64_t addr) {
function rv32_align_address (line 24) | inline uint32_t rv32_align_address(uint32_t addr) {
FILE: vp/src/util/elegantEnums.cpp
function splitString (line 10) | std::vector<std::string> splitString(std::string str, char sep) {
FILE: vp/src/util/elegantEnums.hpp
function generateEnumMap (line 84) | std::map<T, std::string> generateEnumMap(std::string strMap) {
FILE: vp/src/util/gtkwave_riscv-filter.py
function main (line 6) | def main():
FILE: vp/src/util/gtkwave_riscv-filter/riscv-filter.cpp
function string (line 15) | string registerName(uint_fast16_t num) {
function printOpcode (line 23) | void printOpcode(Instruction& instr) {
function main (line 62) | int main(int argc, const char* argv[])
FILE: vp/src/util/memory_map.h
function make_start_end (line 7) | struct RegisterRange {
function RegisterRange (line 52) | static RegisterRange make_start_size(uint64_t start, uint64_t size) {
function contains (line 65) | bool contains(uint64_t addr) {
function to_local (line 69) | uint64_t to_local(uint64_t addr) {
function write (line 73) | void write(uint64_t addr, const uint8_t *src, size_t len, tlm::tlm_gener...
function read (line 90) | void read(uint64_t addr, uint8_t *dst, size_t len, tlm::tlm_generic_payl...
function match (line 106) | bool match(tlm::tlm_generic_payload &trans) {
function process (line 110) | void process(tlm::tlm_generic_payload &trans, sc_core::sc_time &delay) {
function write (line 145) | void write(T value) {
function T (line 191) | T *begin() {
function T (line 194) | const T *begin() const {
function T (line 197) | T *end() {
function T (line 200) | const T *end() const {
function namespace (line 205) | namespace vp {
FILE: vp/src/util/options.h
function T (line 10) | T value{}
function finalize (line 13) | bool finalize(std::function<T(const std::string &)> parser) {
function parse_ulong_option (line 22) | unsigned long parse_ulong_option(const std::string &s) {
FILE: vp/src/util/tlm_map.h
function namespace (line 18) | namespace vp {
type register_access_t (line 127) | struct register_access_t {
function AbstractMapping (line 144) | struct RegisterMapping : public AbstractMapping {
function transport (line 229) | void transport(tlm::tlm_generic_payload &trans, sc_core::sc_time &delay) {
FILE: vp/src/vendor/softfloat/f128_add.c
function float128_t (line 43) | float128_t f128_add( float128_t a, float128_t b )
FILE: vp/src/vendor/softfloat/f128_classify.c
function uint_fast16_t (line 9) | uint_fast16_t f128_classify( float128_t a )
FILE: vp/src/vendor/softfloat/f128_div.c
function float128_t (line 44) | float128_t f128_div( float128_t a, float128_t b )
FILE: vp/src/vendor/softfloat/f128_eq.c
function f128_eq (line 44) | bool f128_eq( float128_t a, float128_t b )
FILE: vp/src/vendor/softfloat/f128_eq_signaling.c
function f128_eq_signaling (line 43) | bool f128_eq_signaling( float128_t a, float128_t b )
FILE: vp/src/vendor/softfloat/f128_isSignalingNaN.c
function f128_isSignalingNaN (line 43) | bool f128_isSignalingNaN( float128_t a )
FILE: vp/src/vendor/softfloat/f128_le.c
function f128_le (line 43) | bool f128_le( float128_t a, float128_t b )
FILE: vp/src/vendor/softfloat/f128_le_quiet.c
function f128_le_quiet (line 44) | bool f128_le_quiet( float128_t a, float128_t b )
FILE: vp/src/vendor/softfloat/f128_lt.c
function f128_lt (line 43) | bool f128_lt( float128_t a, float128_t b )
FILE: vp/src/vendor/softfloat/f128_lt_quiet.c
function f128_lt_quiet (line 44) | bool f128_lt_quiet( float128_t a, float128_t b )
FILE: vp/src/vendor/softfloat/f128_mul.c
function float128_t (line 44) | float128_t f128_mul( float128_t a, float128_t b )
FILE: vp/src/vendor/softfloat/f128_mulAdd.c
function float128_t (line 42) | float128_t f128_mulAdd( float128_t a, float128_t b, float128_t c )
FILE: vp/src/vendor/softfloat/f128_rem.c
function float128_t (line 44) | float128_t f128_rem( float128_t a, float128_t b )
FILE: vp/src/vendor/softfloat/f128_roundToInt.c
function float128_t (line 44) | float128_t
FILE: vp/src/vendor/softfloat/f128_sqrt.c
function float128_t (line 44) | float128_t f128_sqrt( float128_t a )
FILE: vp/src/vendor/softfloat/f128_sub.c
function float128_t (line 43) | float128_t f128_sub( float128_t a, float128_t b )
FILE: vp/src/vendor/softfloat/f128_to_f16.c
function float16_t (line 44) | float16_t f128_to_f16( float128_t a )
FILE: vp/src/vendor/softfloat/f128_to_f32.c
function float32_t (line 44) | float32_t f128_to_f32( float128_t a )
FILE: vp/src/vendor/softfloat/f128_to_f64.c
function float64_t (line 44) | float64_t f128_to_f64( float128_t a )
FILE: vp/src/vendor/softfloat/f128_to_i32.c
function int_fast32_t (line 44) | int_fast32_t f128_to_i32( float128_t a, uint_fast8_t roundingMode, bool ...
FILE: vp/src/vendor/softfloat/f128_to_i32_r_minMag.c
function int_fast32_t (line 44) | int_fast32_t f128_to_i32_r_minMag( float128_t a, bool exact )
FILE: vp/src/vendor/softfloat/f128_to_i64.c
function int_fast64_t (line 44) | int_fast64_t f128_to_i64( float128_t a, uint_fast8_t roundingMode, bool ...
FILE: vp/src/vendor/softfloat/f128_to_i64_r_minMag.c
function int_fast64_t (line 44) | int_fast64_t f128_to_i64_r_minMag( float128_t a, bool exact )
FILE: vp/src/vendor/softfloat/f128_to_ui32.c
function uint_fast32_t (line 44) | uint_fast32_t
FILE: vp/src/vendor/softfloat/f128_to_ui32_r_minMag.c
function uint_fast32_t (line 44) | uint_fast32_t f128_to_ui32_r_minMag( float128_t a, bool exact )
FILE: vp/src/vendor/softfloat/f128_to_ui64.c
function uint_fast64_t (line 44) | uint_fast64_t
FILE: vp/src/vendor/softfloat/f128_to_ui64_r_minMag.c
function uint_fast64_t (line 44) | uint_fast64_t f128_to_ui64_r_minMag( float128_t a, bool exact )
FILE: vp/src/vendor/softfloat/f16_add.c
function float16_t (line 43) | float16_t f16_add( float16_t a, float16_t b )
FILE: vp/src/vendor/softfloat/f16_div.c
function float16_t (line 47) | float16_t f16_div( float16_t a, float16_t b )
FILE: vp/src/vendor/softfloat/f16_eq.c
function f16_eq (line 44) | bool f16_eq( float16_t a, float16_t b )
FILE: vp/src/vendor/softfloat/f16_eq_signaling.c
function f16_eq_signaling (line 43) | bool f16_eq_signaling( float16_t a, float16_t b )
FILE: vp/src/vendor/softfloat/f16_isSignalingNaN.c
function f16_isSignalingNaN (line 43) | bool f16_isSignalingNaN( float16_t a )
FILE: vp/src/vendor/softfloat/f16_le.c
function f16_le (line 43) | bool f16_le( float16_t a, float16_t b )
FILE: vp/src/vendor/softfloat/f16_le_quiet.c
function f16_le_quiet (line 44) | bool f16_le_quiet( float16_t a, float16_t b )
FILE: vp/src/vendor/softfloat/f16_lt.c
function f16_lt (line 43) | bool f16_lt( float16_t a, float16_t b )
FILE: vp/src/vendor/softfloat/f16_lt_quiet.c
function f16_lt_quiet (line 44) | bool f16_lt_quiet( float16_t a, float16_t b )
FILE: vp/src/vendor/softfloat/f16_mul.c
function float16_t (line 44) | float16_t f16_mul( float16_t a, float16_t b )
FILE: vp/src/vendor/softfloat/f16_mulAdd.c
function float16_t (line 42) | float16_t f16_mulAdd( float16_t a, float16_t b, float16_t c )
FILE: vp/src/vendor/softfloat/f16_rem.c
function float16_t (line 44) | float16_t f16_rem( float16_t a, float16_t b )
FILE: vp/src/vendor/softfloat/f16_roundToInt.c
function float16_t (line 44) | float16_t f16_roundToInt( float16_t a, uint_fast8_t roundingMode, bool e...
FILE: vp/src/vendor/softfloat/f16_sqrt.c
function float16_t (line 47) | float16_t f16_sqrt( float16_t a )
FILE: vp/src/vendor/softfloat/f16_sub.c
function float16_t (line 43) | float16_t f16_sub( float16_t a, float16_t b )
FILE: vp/src/vendor/softfloat/f16_to_f128.c
function float128_t (line 44) | float128_t f16_to_f128( float16_t a )
FILE: vp/src/vendor/softfloat/f16_to_f32.c
function float32_t (line 44) | float32_t f16_to_f32( float16_t a )
FILE: vp/src/vendor/softfloat/f16_to_f64.c
function float64_t (line 44) | float64_t f16_to_f64( float16_t a )
FILE: vp/src/vendor/softfloat/f16_to_i32.c
function int_fast32_t (line 44) | int_fast32_t f16_to_i32( float16_t a, uint_fast8_t roundingMode, bool ex...
FILE: vp/src/vendor/softfloat/f16_to_i32_r_minMag.c
function int_fast32_t (line 44) | int_fast32_t f16_to_i32_r_minMag( float16_t a, bool exact )
FILE: vp/src/vendor/softfloat/f16_to_i64.c
function int_fast64_t (line 44) | int_fast64_t f16_to_i64( float16_t a, uint_fast8_t roundingMode, bool ex...
FILE: vp/src/vendor/softfloat/f16_to_i64_r_minMag.c
function int_fast64_t (line 44) | int_fast64_t f16_to_i64_r_minMag( float16_t a, bool exact )
FILE: vp/src/vendor/softfloat/f16_to_ui32.c
function uint_fast32_t (line 44) | uint_fast32_t f16_to_ui32( float16_t a, uint_fast8_t roundingMode, bool ...
FILE: vp/src/vendor/softfloat/f16_to_ui32_r_minMag.c
function uint_fast32_t (line 44) | uint_fast32_t f16_to_ui32_r_minMag( float16_t a, bool exact )
FILE: vp/src/vendor/softfloat/f16_to_ui64.c
function uint_fast64_t (line 44) | uint_fast64_t f16_to_ui64( float16_t a, uint_fast8_t roundingMode, bool ...
FILE: vp/src/vendor/softfloat/f16_to_ui64_r_minMag.c
function uint_fast64_t (line 44) | uint_fast64_t f16_to_ui64_r_minMag( float16_t a, bool exact )
FILE: vp/src/vendor/softfloat/f32_add.c
function float32_t (line 43) | float32_t f32_add( float32_t a, float32_t b )
FILE: vp/src/vendor/softfloat/f32_classify.c
function uint_fast16_t (line 9) | uint_fast16_t f32_classify( float32_t a )
FILE: vp/src/vendor/softfloat/f32_div.c
function float32_t (line 44) | float32_t f32_div( float32_t a, float32_t b )
FILE: vp/src/vendor/softfloat/f32_eq.c
function f32_eq (line 44) | bool f32_eq( float32_t a, float32_t b )
FILE: vp/src/vendor/softfloat/f32_eq_signaling.c
function f32_eq_signaling (line 43) | bool f32_eq_signaling( float32_t a, float32_t b )
FILE: vp/src/vendor/softfloat/f32_isSignalingNaN.c
function f32_isSignalingNaN (line 43) | bool f32_isSignalingNaN( float32_t a )
FILE: vp/src/vendor/softfloat/f32_le.c
function f32_le (line 43) | bool f32_le( float32_t a, float32_t b )
FILE: vp/src/vendor/softfloat/f32_le_quiet.c
function f32_le_quiet (line 44) | bool f32_le_quiet( float32_t a, float32_t b )
FILE: vp/src/vendor/softfloat/f32_lt.c
function f32_lt (line 43) | bool f32_lt( float32_t a, float32_t b )
FILE: vp/src/vendor/softfloat/f32_lt_quiet.c
function f32_lt_quiet (line 44) | bool f32_lt_quiet( float32_t a, float32_t b )
FILE: vp/src/vendor/softfloat/f32_mul.c
function float32_t (line 44) | float32_t f32_mul( float32_t a, float32_t b )
FILE: vp/src/vendor/softfloat/f32_mulAdd.c
function float32_t (line 42) | float32_t f32_mulAdd( float32_t a, float32_t b, float32_t c )
FILE: vp/src/vendor/softfloat/f32_rem.c
function float32_t (line 44) | float32_t f32_rem( float32_t a, float32_t b )
FILE: vp/src/vendor/softfloat/f32_roundToInt.c
function float32_t (line 44) | float32_t f32_roundToInt( float32_t a, uint_fast8_t roundingMode, bool e...
FILE: vp/src/vendor/softfloat/f32_sqrt.c
function float32_t (line 44) | float32_t f32_sqrt( float32_t a )
FILE: vp/src/vendor/softfloat/f32_sub.c
function float32_t (line 43) | float32_t f32_sub( float32_t a, float32_t b )
FILE: vp/src/vendor/softfloat/f32_to_f128.c
function float128_t (line 44) | float128_t f32_to_f128( float32_t a )
FILE: vp/src/vendor/softfloat/f32_to_f16.c
function float16_t (line 44) | float16_t f32_to_f16( float32_t a )
FILE: vp/src/vendor/softfloat/f32_to_f64.c
function float64_t (line 44) | float64_t f32_to_f64( float32_t a )
FILE: vp/src/vendor/softfloat/f32_to_i32.c
function int_fast32_t (line 44) | int_fast32_t f32_to_i32( float32_t a, uint_fast8_t roundingMode, bool ex...
FILE: vp/src/vendor/softfloat/f32_to_i32_r_minMag.c
function int_fast32_t (line 44) | int_fast32_t f32_to_i32_r_minMag( float32_t a, bool exact )
FILE: vp/src/vendor/softfloat/f32_to_i64.c
function int_fast64_t (line 44) | int_fast64_t f32_to_i64( float32_t a, uint_fast8_t roundingMode, bool ex...
FILE: vp/src/vendor/softfloat/f32_to_i64_r_minMag.c
function int_fast64_t (line 44) | int_fast64_t f32_to_i64_r_minMag( float32_t a, bool exact )
FILE: vp/src/vendor/softfloat/f32_to_ui32.c
function uint_fast32_t (line 44) | uint_fast32_t f32_to_ui32( float32_t a, uint_fast8_t roundingMode, bool ...
FILE: vp/src/vendor/softfloat/f32_to_ui32_r_minMag.c
function uint_fast32_t (line 44) | uint_fast32_t f32_to_ui32_r_minMag( float32_t a, bool exact )
FILE: vp/src/vendor/softfloat/f32_to_ui64.c
function uint_fast64_t (line 44) | uint_fast64_t f32_to_ui64( float32_t a, uint_fast8_t roundingMode, bool ...
FILE: vp/src/vendor/softfloat/f32_to_ui64_r_minMag.c
function uint_fast64_t (line 44) | uint_fast64_t f32_to_ui64_r_minMag( float32_t a, bool exact )
FILE: vp/src/vendor/softfloat/f64_add.c
function float64_t (line 43) | float64_t f64_add( float64_t a, float64_t b )
FILE: vp/src/vendor/softfloat/f64_classify.c
function uint_fast16_t (line 9) | uint_fast16_t f64_classify( float64_t a )
FILE: vp/src/vendor/softfloat/f64_div.c
function float64_t (line 44) | float64_t f64_div( float64_t a, float64_t b )
FILE: vp/src/vendor/softfloat/f64_eq.c
function f64_eq (line 44) | bool f64_eq( float64_t a, float64_t b )
FILE: vp/src/vendor/softfloat/f64_eq_signaling.c
function f64_eq_signaling (line 43) | bool f64_eq_signaling( float64_t a, float64_t b )
FILE: vp/src/vendor/softfloat/f64_isSignalingNaN.c
function f64_isSignalingNaN (line 43) | bool f64_isSignalingNaN( float64_t a )
FILE: vp/src/vendor/softfloat/f64_le.c
function f64_le (line 43) | bool f64_le( float64_t a, float64_t b )
FILE: vp/src/vendor/softfloat/f64_le_quiet.c
function f64_le_quiet (line 44) | bool f64_le_quiet( float64_t a, float64_t b )
FILE: vp/src/vendor/softfloat/f64_lt.c
function f64_lt (line 43) | bool f64_lt( float64_t a, float64_t b )
FILE: vp/src/vendor/softfloat/f64_lt_quiet.c
function f64_lt_quiet (line 44) | bool f64_lt_quiet( float64_t a, float64_t b )
FILE: vp/src/vendor/softfloat/f64_mul.c
function float64_t (line 44) | float64_t f64_mul( float64_t a, float64_t b )
FILE: vp/src/vendor/softfloat/f64_mulAdd.c
function float64_t (line 42) | float64_t f64_mulAdd( float64_t a, float64_t b, float64_t c )
FILE: vp/src/vendor/softfloat/f64_rem.c
function float64_t (line 44) | float64_t f64_rem( float64_t a, float64_t b )
FILE: vp/src/vendor/softfloat/f64_roundToInt.c
function float64_t (line 44) | float64_t f64_roundToInt( float64_t a, uint_fast8_t roundingMode, bool e...
FILE: vp/src/vendor/softfloat/f64_sqrt.c
function float64_t (line 44) | float64_t f64_sqrt( float64_t a )
FILE: vp/src/vendor/softfloat/f64_sub.c
function float64_t (line 43) | float64_t f64_sub( float64_t a, float64_t b )
FILE: vp/src/vendor/softfloat/f64_to_f128.c
function float128_t (line 44) | float128_t f64_to_f128( float64_t a )
FILE: vp/src/vendor/softfloat/f64_to_f16.c
function float16_t (line 44) | float16_t f64_to_f16( float64_t a )
FILE: vp/src/vendor/softfloat/f64_to_f32.c
function float32_t (line 44) | float32_t f64_to_f32( float64_t a )
FILE: vp/src/vendor/softfloat/f64_to_i32.c
function int_fast32_t (line 44) | int_fast32_t f64_to_i32( float64_t a, uint_fast8_t roundingMode, bool ex...
FILE: vp/src/vendor/softfloat/f64_to_i32_r_minMag.c
function int_fast32_t (line 44) | int_fast32_t f64_to_i32_r_minMag( float64_t a, bool exact )
FILE: vp/src/vendor/softfloat/f64_to_i64.c
function int_fast64_t (line 44) | int_fast64_t f64_to_i64( float64_t a, uint_fast8_t roundingMode, bool ex...
FILE: vp/src/vendor/softfloat/f64_to_i64_r_minMag.c
function int_fast64_t (line 44) | int_fast64_t f64_to_i64_r_minMag( float64_t a, bool exact )
FILE: vp/src/vendor/softfloat/f64_to_ui32.c
function uint_fast32_t (line 44) | uint_fast32_t f64_to_ui32( float64_t a, uint_fast8_t roundingMode, bool ...
FILE: vp/src/vendor/softfloat/f64_to_ui32_r_minMag.c
function uint_fast32_t (line 44) | uint_fast32_t f64_to_ui32_r_minMag( float64_t a, bool exact )
FILE: vp/src/vendor/softfloat/f64_to_ui64.c
function uint_fast64_t (line 44) | uint_fast64_t f64_to_ui64( float64_t a, uint_fast8_t roundingMode, bool ...
FILE: vp/src/vendor/softfloat/f64_to_ui64_r_minMag.c
function uint_fast64_t (line 44) | uint_fast64_t f64_to_ui64_r_minMag( float64_t a, bool exact )
FILE: vp/src/vendor/softfloat/i32_to_f128.c
function float128_t (line 42) | float128_t i32_to_f128( int32_t a )
FILE: vp/src/vendor/softfloat/i32_to_f16.c
function float16_t (line 43) | float16_t i32_to_f16( int32_t a )
FILE: vp/src/vendor/softfloat/i32_to_f32.c
function float32_t (line 43) | float32_t i32_to_f32( int32_t a )
FILE: vp/src/vendor/softfloat/i32_to_f64.c
function float64_t (line 43) | float64_t i32_to_f64( int32_t a )
FILE: vp/src/vendor/softfloat/i64_to_f128.c
function float128_t (line 42) | float128_t i64_to_f128( int64_t a )
FILE: vp/src/vendor/softfloat/i64_to_f16.c
function float16_t (line 43) | float16_t i64_to_f16( int64_t a )
FILE: vp/src/vendor/softfloat/i64_to_f32.c
function float32_t (line 43) | float32_t i64_to_f32( int64_t a )
FILE: vp/src/vendor/softfloat/i64_to_f64.c
function float64_t (line 43) | float64_t i64_to_f64( int64_t a )
FILE: vp/src/vendor/softfloat/include/softfloat/internals.h
type extFloat80M (line 54) | struct extFloat80M
type uint128 (line 55) | struct uint128
type exp8_sig16 (line 94) | struct exp8_sig16 { int_fast8_t exp; uint_fast16_t sig; }
type exp8_sig16 (line 95) | struct exp8_sig16
type exp16_sig32 (line 115) | struct exp16_sig32 { int_fast16_t exp; uint_fast32_t sig; }
type exp16_sig32 (line 116) | struct exp16_sig32
type exp16_sig64 (line 136) | struct exp16_sig64 { int_fast16_t exp; uint_fast64_t sig; }
type exp16_sig64 (line 137) | struct exp16_sig64
type exp32_sig64 (line 161) | struct exp32_sig64 { int_fast32_t exp; uint64_t sig; }
type exp32_sig64 (line 162) | struct exp32_sig64
type exp32_sig128 (line 187) | struct exp32_sig128 { int_fast32_t exp; struct uint128 sig; }
type exp32_sig128 (line 188) | struct exp32_sig128
type extFloat80M (line 222) | struct extFloat80M
type extFloat80M (line 223) | struct extFloat80M
type extFloat80M (line 224) | struct extFloat80M
type extFloat80M (line 226) | struct extFloat80M
type extFloat80M (line 232) | struct extFloat80M
type extFloat80M (line 235) | struct extFloat80M
type extFloat80M (line 239) | struct extFloat80M
type extFloat80M (line 240) | struct extFloat80M
type extFloat80M (line 241) | struct extFloat80M
type extFloat80M (line 247) | struct extFloat80M
type extFloat80M (line 247) | struct extFloat80M
FILE: vp/src/vendor/softfloat/include/softfloat/primitiveTypes.h
type uint128 (line 46) | struct uint128 { uint64_t v0, v64; }
type uint64_extra (line 47) | struct uint64_extra { uint64_t extra, v; }
type uint128_extra (line 48) | struct uint128_extra { uint64_t extra; struct uint128 v; }
type uint128 (line 50) | struct uint128 { uint64_t v64, v0; }
type uint64_extra (line 51) | struct uint64_extra { uint64_t v, extra; }
type uint128_extra (line 52) | struct uint128_extra { struct uint128 v; uint64_t extra; }
FILE: vp/src/vendor/softfloat/include/softfloat/primitives.h
function INLINE (line 56) | INLINE
function INLINE (line 75) | INLINE uint32_t softfloat_shiftRightJam32( uint32_t a, uint_fast16_t dist )
function INLINE (line 96) | INLINE uint64_t softfloat_shiftRightJam64( uint64_t a, uint_fast32_t dist )
function INLINE (line 119) | INLINE uint_fast8_t softfloat_countLeadingZeros16( uint16_t a )
function INLINE (line 140) | INLINE uint_fast8_t softfloat_countLeadingZeros32( uint32_t a )
function INLINE (line 228) | INLINE
function INLINE (line 243) | INLINE
function INLINE (line 258) | INLINE
function uint128 (line 273) | uint128
type uint128 (line 282) | struct uint128
function uint128 (line 294) | uint128
type uint128 (line 303) | struct uint128
function uint64_extra (line 315) | uint64_extra
type uint64_extra (line 325) | struct uint64_extra
function uint128 (line 341) | uint128
type uint128 (line 354) | struct uint128
function uint128_extra (line 367) | uint128_extra
type uint128_extra (line 379) | struct uint128_extra
function uint64_extra (line 404) | uint64_extra
type uint64_extra (line 420) | struct uint64_extra
type uint128 (line 437) | struct uint128
type uint128_extra (line 459) | struct uint128_extra
function uint128 (line 490) | uint128
type uint128 (line 499) | struct uint128
function uint128 (line 525) | uint128
type uint128 (line 535) | struct uint128
function uint128 (line 559) | uint128 softfloat_mul64ByShifted32To128( uint64_t a, uint32_t b )
type uint128 (line 569) | struct uint128
type uint128 (line 577) | struct uint128
function uint128 (line 588) | uint128 softfloat_mul128By32( uint64_t a64, uint64_t a0, uint32_t b )
type uint128 (line 600) | struct uint128
function INLINE (line 658) | INLINE
FILE: vp/src/vendor/softfloat/include/softfloat/softfloat_types.h
type float16_t (line 50) | typedef struct { uint16_t v; } float16_t;
type float32_t (line 51) | typedef struct { uint32_t v; } float32_t;
type float64_t (line 52) | typedef struct { uint64_t v; } float64_t;
type float128_t (line 53) | typedef struct { uint64_t v[2]; } float128_t;
type extFloat80M (line 61) | struct extFloat80M { uint64_t signif; uint16_t signExp; }
type extFloat80M (line 63) | struct extFloat80M { uint16_t signExp; uint64_t signif; }
type extFloat80_t (line 78) | typedef struct extFloat80M extFloat80_t;
FILE: vp/src/vendor/softfloat/include/softfloat/specialize.h
type commonNaN (line 80) | struct commonNaN { char _unused; }
function uint128 (line 224) | uint128 softfloat_commonNaNToExtF80UI( const struct commonNaN *aPtr )
type uint128 (line 232) | struct uint128
type commonNaN (line 232) | struct commonNaN
type uint128 (line 244) | struct uint128
function uint128 (line 281) | uint128 softfloat_commonNaNToF128UI( const struct commonNaN *aPtr )
type uint128 (line 289) | struct uint128
type commonNaN (line 289) | struct commonNaN
type uint128 (line 301) | struct uint128
function INLINE (line 330) | INLINE
type commonNaN (line 341) | struct commonNaN
type extFloat80M (line 341) | struct extFloat80M
type extFloat80M (line 352) | struct extFloat80M
type extFloat80M (line 353) | struct extFloat80M
type extFloat80M (line 354) | struct extFloat80M
function INLINE (line 382) | INLINE
type commonNaN (line 393) | struct commonNaN
FILE: vp/src/vendor/softfloat/s_add128.c
function softfloat_add128 (line 43) | struct uint128
FILE: vp/src/vendor/softfloat/s_add256M.c
function softfloat_add256M (line 43) | void
FILE: vp/src/vendor/softfloat/s_addCarryM.c
function uint_fast8_t (line 43) | uint_fast8_t
FILE: vp/src/vendor/softfloat/s_addComplCarryM.c
function uint_fast8_t (line 43) | uint_fast8_t
FILE: vp/src/vendor/softfloat/s_addM.c
function softfloat_addM (line 43) | void
FILE: vp/src/vendor/softfloat/s_addMagsF128.c
function float128_t (line 43) | float128_t
FILE: vp/src/vendor/softfloat/s_addMagsF16.c
function float16_t (line 44) | float16_t softfloat_addMagsF16( uint_fast16_t uiA, uint_fast16_t uiB )
FILE: vp/src/vendor/softfloat/s_addMagsF32.c
function float32_t (line 43) | float32_t softfloat_addMagsF32( uint_fast32_t uiA, uint_fast32_t uiB )
FILE: vp/src/vendor/softfloat/s_addMagsF64.c
function float64_t (line 43) | float64_t
FILE: vp/src/vendor/softfloat/s_approxRecip32_1.c
function softfloat_approxRecip32_1 (line 45) | uint32_t softfloat_approxRecip32_1( uint32_t a )
FILE: vp/src/vendor/softfloat/s_approxRecipSqrt32_1.c
function softfloat_approxRecipSqrt32_1 (line 45) | uint32_t softfloat_approxRecipSqrt32_1( unsigned int oddExpA, uint32_t a )
FILE: vp/src/vendor/softfloat/s_commonNaNToF128UI.c
function softfloat_commonNaNToF128UI (line 47) | struct uint128 softfloat_commonNaNToF128UI( const struct commonNaN *aPtr )
FILE: vp/src/vendor/softfloat/s_compare128M.c
function int_fast8_t (line 43) | int_fast8_t softfloat_compare128M( const uint32_t *aPtr, const uint32_t ...
FILE: vp/src/vendor/softfloat/s_compare96M.c
function int_fast8_t (line 43) | int_fast8_t softfloat_compare96M( const uint32_t *aPtr, const uint32_t *...
FILE: vp/src/vendor/softfloat/s_countLeadingZeros16.c
function uint_fast8_t (line 45) | uint_fast8_t softfloat_countLeadingZeros16( uint16_t a )
FILE: vp/src/vendor/softfloat/s_countLeadingZeros32.c
function uint_fast8_t (line 45) | uint_fast8_t softfloat_countLeadingZeros32( uint32_t a )
FILE: vp/src/vendor/softfloat/s_countLeadingZeros64.c
function uint_fast8_t (line 45) | uint_fast8_t softfloat_countLeadingZeros64( uint64_t a )
FILE: vp/src/vendor/softfloat/s_eq128.c
function softfloat_eq128 (line 43) | bool softfloat_eq128( uint64_t a64, uint64_t a0, uint64_t b64, uint64_t ...
FILE: vp/src/vendor/softfloat/s_le128.c
function softfloat_le128 (line 43) | bool softfloat_le128( uint64_t a64, uint64_t a0, uint64_t b64, uint64_t ...
FILE: vp/src/vendor/softfloat/s_lt128.c
function softfloat_lt128 (line 43) | bool softfloat_lt128( uint64_t a64, uint64_t a0, uint64_t b64, uint64_t ...
FILE: vp/src/vendor/softfloat/s_mul128By32.c
function softfloat_mul128By32 (line 43) | struct uint128 softfloat_mul128By32( uint64_t a64, uint64_t a0, uint32_t...
FILE: vp/src/vendor/softfloat/s_mul128MTo256M.c
function softfloat_mul128MTo256M (line 43) | void
FILE: vp/src/vendor/softfloat/s_mul128To256M.c
function softfloat_mul128To256M (line 45) | void
FILE: vp/src/vendor/softfloat/s_mul64ByShifted32To128.c
function softfloat_mul64ByShifted32To128 (line 43) | struct uint128 softfloat_mul64ByShifted32To128( uint64_t a, uint32_t b )
FILE: vp/src/vendor/softfloat/s_mul64To128.c
function softfloat_mul64To128 (line 43) | struct uint128 softfloat_mul64To128( uint64_t a, uint64_t b )
FILE: vp/src/vendor/softfloat/s_mul64To128M.c
function softfloat_mul64To128M (line 43) | void softfloat_mul64To128M( uint64_t a, uint64_t b, uint32_t *zPtr )
FILE: vp/src/vendor/softfloat/s_mulAddF128.c
function float128_t (line 44) | float128_t
FILE: vp/src/vendor/softfloat/s_mulAddF16.c
function float16_t (line 44) | float16_t
FILE: vp/src/vendor/softfloat/s_mulAddF32.c
function float32_t (line 44) | float32_t
FILE: vp/src/vendor/softfloat/s_mulAddF64.c
function float64_t (line 46) | float64_t
function float64_t (line 246) | float64_t
FILE: vp/src/vendor/softfloat/s_negXM.c
function softfloat_negXM (line 43) | void softfloat_negXM( uint_fast8_t size_words, uint32_t *zPtr )
FILE: vp/src/vendor/softfloat/s_normRoundPackToF128.c
function float128_t (line 42) | float128_t
FILE: vp/src/vendor/softfloat/s_normRoundPackToF16.c
function float16_t (line 42) | float16_t
FILE: vp/src/vendor/softfloat/s_normRoundPackToF32.c
function float32_t (line 42) | float32_t
FILE: vp/src/vendor/softfloat/s_normRoundPackToF64.c
function float64_t (line 42) | float64_t
FILE: vp/src/vendor/softfloat/s_normSubnormalF128Sig.c
function softfloat_normSubnormalF128Sig (line 41) | struct exp32_sig128
FILE: vp/src/vendor/softfloat/s_normSubnormalF16Sig.c
function softfloat_normSubnormalF16Sig (line 41) | struct exp8_sig16 softfloat_normSubnormalF16Sig( uint_fast16_t sig )
FILE: vp/src/vendor/softfloat/s_normSubnormalF32Sig.c
function softfloat_normSubnormalF32Sig (line 41) | struct exp16_sig32 softfloat_normSubnormalF32Sig( uint_fast32_t sig )
FILE: vp/src/vendor/softfloat/s_normSubnormalF64Sig.c
function softfloat_normSubnormalF64Sig (line 41) | struct exp16_sig64 softfloat_normSubnormalF64Sig( uint_fast64_t sig )
FILE: vp/src/vendor/softfloat/s_propagateNaNF128UI.c
function softfloat_propagateNaNF128UI (line 52) | struct uint128
FILE: vp/src/vendor/softfloat/s_propagateNaNF16UI.c
function uint_fast16_t (line 48) | uint_fast16_t
FILE: vp/src/vendor/softfloat/s_propagateNaNF32UI.c
function uint_fast32_t (line 48) | uint_fast32_t
FILE: vp/src/vendor/softfloat/s_propagateNaNF64UI.c
function uint_fast64_t (line 48) | uint_fast64_t
FILE: vp/src/vendor/softfloat/s_remStepMBy32.c
function softfloat_remStepMBy32 (line 43) | void
FILE: vp/src/vendor/softfloat/s_roundMToI64.c
function int_fast64_t (line 44) | int_fast64_t
FILE: vp/src/vendor/softfloat/s_roundMToUI64.c
function uint_fast64_t (line 44) | uint_fast64_t
FILE: vp/src/vendor/softfloat/s_roundPackMToI64.c
function int_fast64_t (line 44) | int_fast64_t
FILE: vp/src/vendor/softfloat/s_roundPackMToUI64.c
function uint_fast64_t (line 44) | uint_fast64_t
FILE: vp/src/vendor/softfloat/s_roundPackToF128.c
function float128_t (line 43) | float128_t
FILE: vp/src/vendor/softfloat/s_roundPackToF16.c
function float16_t (line 43) | float16_t
FILE: vp/src/vendor/softfloat/s_roundPackToF32.c
function float32_t (line 43) | float32_t
FILE: vp/src/vendor/softfloat/s_roundPackToF64.c
function float64_t (line 43) | float64_t
FILE: vp/src/vendor/softfloat/s_roundPackToI32.c
function int_fast32_t (line 44) | int_fast32_t
FILE: vp/src/vendor/softfloat/s_roundPackToI64.c
function int_fast64_t (line 44) | int_fast64_t
FILE: vp/src/vendor/softfloat/s_roundPackToUI32.c
function uint_fast32_t (line 44) | uint_fast32_t
FILE: vp/src/vendor/softfloat/s_roundPackToUI64.c
function uint_fast64_t (line 44) | uint_fast64_t
FILE: vp/src/vendor/softfloat/s_roundToI32.c
function int_fast32_t (line 44) | int_fast32_t
FILE: vp/src/vendor/softfloat/s_roundToI64.c
function int_fast64_t (line 44) | int_fast64_t
FILE: vp/src/vendor/softfloat/s_roundToUI32.c
function uint_fast32_t (line 44) | uint_fast32_t
FILE: vp/src/vendor/softfloat/s_roundToUI64.c
function uint_fast64_t (line 44) | uint_fast64_t
FILE: vp/src/vendor/softfloat/s_shiftRightJam128.c
function softfloat_shiftRightJam128 (line 43) | struct uint128
FILE: vp/src/vendor/softfloat/s_shiftRightJam128Extra.c
function softfloat_shiftRightJam128Extra (line 43) | struct uint128_extra
FILE: vp/src/vendor/softfloat/s_shiftRightJam256M.c
function softfloat_shortShiftRightJamM (line 43) | static
function softfloat_shiftRightJam256M (line 72) | void
FILE: vp/src/vendor/softfloat/s_shiftRightJam32.c
function softfloat_shiftRightJam32 (line 42) | uint32_t softfloat_shiftRightJam32( uint32_t a, uint_fast16_t dist )
FILE: vp/src/vendor/softfloat/s_shiftRightJam64.c
function softfloat_shiftRightJam64 (line 42) | uint64_t softfloat_shiftRightJam64( uint64_t a, uint_fast32_t dist )
FILE: vp/src/vendor/softfloat/s_shiftRightJam64Extra.c
function softfloat_shiftRightJam64Extra (line 43) | struct uint64_extra
FILE: vp/src/vendor/softfloat/s_shortShiftLeft128.c
function softfloat_shortShiftLeft128 (line 43) | struct uint128
FILE: vp/src/vendor/softfloat/s_shortShiftLeft64To96M.c
function softfloat_shortShiftLeft64To96M (line 43) | void
FILE: vp/src/vendor/softfloat/s_shortShiftRight128.c
function softfloat_shortShiftRight128 (line 43) | struct uint128
FILE: vp/src/vendor/softfloat/s_shortShiftRightExtendM.c
function softfloat_shortShiftRightExtendM (line 43) | void
FILE: vp/src/vendor/softfloat/s_shortShiftRightJam128.c
function softfloat_shortShiftRightJam128 (line 43) | struct uint128
FILE: vp/src/vendor/softfloat/s_shortShiftRightJam128Extra.c
function softfloat_shortShiftRightJam128Extra (line 43) | struct uint128_extra
FILE: vp/src/vendor/softfloat/s_shortShiftRightJam64.c
function softfloat_shortShiftRightJam64 (line 42) | uint64_t softfloat_shortShiftRightJam64( uint64_t a, uint_fast8_t dist )
FILE: vp/src/vendor/softfloat/s_shortShiftRightJam64Extra.c
function softfloat_shortShiftRightJam64Extra (line 43) | struct uint64_extra
FILE: vp/src/vendor/softfloat/s_shortShiftRightM.c
function softfloat_shortShiftRightM (line 43) | void
FILE: vp/src/vendor/softfloat/s_sub128.c
function softfloat_sub128 (line 43) | struct uint128
FILE: vp/src/vendor/softfloat/s_sub1XM.c
function softfloat_sub1XM (line 43) | void softfloat_sub1XM( uint_fast8_t size_words, uint32_t *zPtr )
FILE: vp/src/vendor/softfloat/s_sub256M.c
function softfloat_sub256M (line 43) | void
FILE: vp/src/vendor/softfloat/s_subM.c
function softfloat_subM (line 43) | void
FILE: vp/src/vendor/softfloat/s_subMagsF128.c
function float128_t (line 44) | float128_t
FILE: vp/src/vendor/softfloat/s_subMagsF16.c
function float16_t (line 44) | float16_t softfloat_subMagsF16( uint_fast16_t uiA, uint_fast16_t uiB )
FILE: vp/src/vendor/softfloat/s_subMagsF32.c
function float32_t (line 44) | float32_t softfloat_subMagsF32( uint_fast32_t uiA, uint_fast32_t uiB )
FILE: vp/src/vendor/softfloat/s_subMagsF64.c
function float64_t (line 44) | float64_t
FILE: vp/src/vendor/softfloat/softfloat_raiseFlags.c
function softfloat_raiseFlags (line 46) | void softfloat_raiseFlags( uint_fast8_t flags )
FILE: vp/src/vendor/softfloat/ui32_to_f128.c
function float128_t (line 42) | float128_t ui32_to_f128( uint32_t a )
FILE: vp/src/vendor/softfloat/ui32_to_f16.c
function float16_t (line 42) | float16_t ui32_to_f16( uint32_t a )
FILE: vp/src/vendor/softfloat/ui32_to_f32.c
function float32_t (line 42) | float32_t ui32_to_f32( uint32_t a )
FILE: vp/src/vendor/softfloat/ui32_to_f64.c
function float64_t (line 42) | float64_t ui32_to_f64( uint32_t a )
FILE: vp/src/vendor/softfloat/ui64_to_f128.c
function float128_t (line 42) | float128_t ui64_to_f128( uint64_t a )
FILE: vp/src/vendor/softfloat/ui64_to_f16.c
function float16_t (line 42) | float16_t ui64_to_f16( uint64_t a )
FILE: vp/src/vendor/softfloat/ui64_to_f32.c
function float32_t (line 42) | float32_t ui64_to_f32( uint64_t a )
FILE: vp/src/vendor/softfloat/ui64_to_f64.c
function float64_t (line 42) | float64_t ui64_to_f64( uint64_t a )
Condensed preview — 513 files, each showing path, character count, and a content snippet. Download the .json file or copy for the full structured content (1,692K chars).
[
{
"path": ".clang-format",
"chars": 231,
"preview": "---\nBasedOnStyle: Google\nColumnLimit: '120'\nAllowShortCaseLabelsOnASingleLine: 'false'\nAllowShortFunctionsOnASingleLine"
},
{
"path": ".gitignore",
"chars": 255,
"preview": ".cproject\n.project\n.settings/\nmain\nbuild/\nvp/dependencies/systemc-dist/\n*.bin\nsystemc-*\n*.asm\n**/nbproject/private/\n**/n"
},
{
"path": ".gitlab-ci.yml",
"chars": 653,
"preview": "image: alpine:3.19\n\nvariables:\n GIT_SUBMODULE_STRATEGY: recursive\n\ncache:\n key: $CI_COMMIT_REF_SLUG\n paths:\n - vp/"
},
{
"path": ".gitmodules",
"chars": 688,
"preview": "[submodule \"vp/src/core/common/gdb-mc/parser/mpc\"]\n\tpath = vp/src/core/common/gdb-mc/libgdb/mpc\n\turl = https://github.co"
},
{
"path": "CITATION.cff",
"chars": 1114,
"preview": "# This CITATION.cff file was generated with cffinit.\n# Visit https://bit.ly/cffinit to generate yours today!\n\ncff-versio"
},
{
"path": "Dockerfile",
"chars": 757,
"preview": "# XXX: Need Alpine Linux Edge since the latest release (3.19)\n# only ships SystemC 2.3.3 and does hence not support aarc"
},
{
"path": "LICENSE",
"chars": 1134,
"preview": "Copyright (c) 2017-2018 Group of Computer Architecture, University of Bremen <riscv@systemc-verification.org>\n\nPermissio"
},
{
"path": "Makefile",
"chars": 1065,
"preview": "MAKEFLAGS += --no-print-directory\n\n# Whether to use a system-wide SystemC library instead of the vendored one.\nUSE_SYSTE"
},
{
"path": "README.md",
"chars": 6135,
"preview": "# RISC-V based Virtual Prototype (VP)\n\n<p align=\"center\">\n <img src=\"./img/riscv-vp_logo.png\" alt=\"RISC-V based Virtual"
},
{
"path": "env/basic/vp-display/CMakeLists.txt",
"chars": 593,
"preview": "cmake_minimum_required(VERSION 3.1.0)\nproject(vp-display) # Your project name\n\nset(CMAKE_CXX_STANDARD 11) # This is equa"
},
{
"path": "env/basic/vp-display/VP-Display.pro",
"chars": 1108,
"preview": "#-------------------------------------------------\n#\n# Project created by QtCreator 2018-09-10T15:30:06\n#\n#-------------"
},
{
"path": "env/basic/vp-display/framebuffer.h",
"chars": 1715,
"preview": "#pragma once\n#include <inttypes.h>\n#include <cassert>\n#include <cstring>\n\n#define SHMKEY 1338\n\nstruct Framebuffer {\n\tsta"
},
{
"path": "env/basic/vp-display/main.cpp",
"chars": 159,
"preview": "#include <QApplication>\n#include \"mainwindow.h\"\n\nint main(int argc, char *argv[]) {\n\tQApplication a(argc, argv);\n\tVPDisp"
},
{
"path": "env/basic/vp-display/mainwindow.cpp",
"chars": 1358,
"preview": "#include \"mainwindow.h\"\n#include <qpainter.h>\n#include <cassert>\n#include \"framebuffer.h\"\n#include \"ui_mainwindow.h\"\n\nVP"
},
{
"path": "env/basic/vp-display/mainwindow.h",
"chars": 435,
"preview": "#pragma once\n#include <QMainWindow>\n#include <cassert>\n#include \"vpdisplayserver.h\"\n\nnamespace Ui {\nclass VPDisplay;\n}\n\n"
},
{
"path": "env/basic/vp-display/mainwindow.ui",
"chars": 630,
"preview": "<ui version=\"4.0\">\n <class>MainWindow</class>\n <widget class=\"QMainWindow\" name=\"MainWindow\" >\n <property name=\"geometr"
},
{
"path": "env/basic/vp-display/vpdisplayserver.cpp",
"chars": 1202,
"preview": "#include \"vpdisplayserver.h\"\n#include <stdio.h>\n#include <stdlib.h>\n#include <sys/ipc.h>\n#include <sys/shm.h>\n#include <"
},
{
"path": "env/basic/vp-display/vpdisplayserver.h",
"chars": 411,
"preview": "#pragma once\n#include <atomic>\n#include <functional>\n#include <thread>\n#include \"framebuffer.h\"\n\nclass VPDisplayserver {"
},
{
"path": "sw/.gitignore",
"chars": 5,
"preview": "main\n"
},
{
"path": "sw/Makefile",
"chars": 177,
"preview": "all:\n\tfind . -maxdepth 1 -type d \\( ! -name . \\) -exec bash -c \"cd '{}' && make\" \\;\n\nclean:\n\tfind . -maxdepth 1 -type d "
},
{
"path": "sw/Makefile.common",
"chars": 1434,
"preview": "RISCV_PREFIX ?= riscv32-unknown-elf-\n\noverride CC = $(RISCV_PREFIX)gcc\noverride CXX = $(RISCV_PREFIX)g++\noverride LD = $"
},
{
"path": "sw/README.md",
"chars": 1461,
"preview": "These SW examples demonstrate basic bare-metal applications and applications that use the C-library. In particular, the "
},
{
"path": "sw/basic-asm/Makefile",
"chars": 165,
"preview": "OBJECTS = sum.o\nCFLAGS = -march=rv32i -mabi=ilp32\nLDFLAGS = -nostartfiles -Wl,--no-relax\nVP_FLAGS = --error-on-zero-"
},
{
"path": "sw/basic-asm/sum.S",
"chars": 355,
"preview": ".globl _start\n.equ SYSCALL_ADDR, 0x02010000\n\n.macro SYS_EXIT, exit_code\nli a7, 93\nli a0, \\exit_code\nli t0, SYSCALL"
},
{
"path": "sw/basic-c/Makefile",
"chars": 140,
"preview": "OBJECTS = main.o sum.o bootstrap.o\nCFLAGS = -march=rv32i -mabi=ilp32\nLDFLAGS = -nostartfiles -Wl,--no-relax\n\ninclude"
},
{
"path": "sw/basic-c/bootstrap.S",
"chars": 128,
"preview": ".globl _start\n.globl main\n\n_start:\njal main\n\n# call exit (SYS_EXIT=93) with exit code 0 (argument in a0)\nli a7,93\nli a0,"
},
{
"path": "sw/basic-c/main.c",
"chars": 121,
"preview": "int sum(int end);\n\nint x = 5;\nint y;\n\nint main() {\n\tint a = 6;\n\tint b = 7;\n\ta = a + b + x + y;\n\ta = sum(a);\n\treturn a;\n}"
},
{
"path": "sw/basic-c/sum.c",
"chars": 94,
"preview": "int sum(int end) {\n\tint ans = end;\n\tfor (int i=1; i<end; ++i) {\n\t\tans += i;\n\t}\n\treturn ans;\n}\n"
},
{
"path": "sw/basic-debug/Makefile",
"chars": 217,
"preview": "OBJECTS = main.o bootstrap.o\nCFLAGS = -g3 -march=rv32im -mabi=ilp32\nLDFLAGS = -nostartfiles -Wl,--no-relax\nVP_FLAGS "
},
{
"path": "sw/basic-debug/bootstrap.S",
"chars": 137,
"preview": ".align 6\n.globl _start\n.globl main\n\n_start:\njal main\n\n# call exit (SYS_EXIT=93) with exit code 0 (argument in a0)\nli a7,"
},
{
"path": "sw/basic-debug/eclipse-remote-debug-readme.txt",
"chars": 959,
"preview": "Start Eclipse\n\nFile -> New -> Makefile Project with Existing Code\n\n Select the software folder containing the Makefil"
},
{
"path": "sw/basic-debug/main.c",
"chars": 212,
"preview": "int x = 5;\nint y;\n\nint f(int a, int b) {\n\tif (a > 0) {\n\t\tint ans = a + b;\n\t\treturn ans;\n\t}\n\ta = -a;\n\treturn b + a;\n}\n\nin"
},
{
"path": "sw/basic-debug/remote-debug-readme.txt",
"chars": 636,
"preview": "In the first terminal run our VP in debug mode (wraps the core iss in a debug stub):\n\n\triscv-vp --debug-mode --intercept"
},
{
"path": "sw/basic-debug/test-ignore",
"chars": 0,
"preview": ""
},
{
"path": "sw/basic-dma/Makefile",
"chars": 143,
"preview": "OBJECTS = main.o irq.o bootstrap.o\nCFLAGS = -march=rv32imac -mabi=ilp32\nLDFLAGS = -nostartfiles -Wl,--no-relax\n\nincl"
},
{
"path": "sw/basic-dma/bootstrap.S",
"chars": 1830,
"preview": ".globl _start\n.globl init\n.globl main\n.globl level_1_interrupt_handler\n\n.equ PLIC_ENABLED_IRQ_ADDR, 0x40002000\n\n_start:\n"
},
{
"path": "sw/basic-dma/irq.c",
"chars": 2058,
"preview": "#include \"irq.h\"\n#include \"assert.h\"\n\n\n#define RISCV_MACHINE_SOFTWARE_INTERRUPT 3\n#define RISCV_MACHINE_TIMER_INTERRUPT "
},
{
"path": "sw/basic-dma/irq.h",
"chars": 312,
"preview": "#ifndef __RISCV_IRQ_H__\n#define __RISCV_IRQ_H__\n\n#include \"stdint.h\"\n\ntypedef void (*irq_handler_t)(void);\n\nvoid registe"
},
{
"path": "sw/basic-dma/main.c",
"chars": 1129,
"preview": "#include \"stdint.h\"\n\n#include \"irq.h\"\n\n\nstatic volatile char * const TERMINAL_ADDR = (char * const)0x20000000;\n\nstatic v"
},
{
"path": "sw/basic-e/Makefile",
"chars": 183,
"preview": "OBJECTS = sum.o\nCFLAGS = -march=rv32e -mabi=ilp32e\nLDFLAGS = -nostartfiles -Wl,--no-relax\nVP_FLAGS = --use-E-base-is"
},
{
"path": "sw/basic-e/sum.S",
"chars": 355,
"preview": ".globl _start\n.equ SYSCALL_ADDR, 0x02010000\n\n.macro SYS_EXIT, exit_code\nli a5, 93\nli a0, \\exit_code\nli t0, SYSCALL"
},
{
"path": "sw/basic-gcov/Makefile",
"chars": 543,
"preview": "OBJECTS = main.o\nCFLAGS = --coverage -march=rv32ima -mabi=ilp32\nLDFLAGS = --coverage\nVP_FLAGS = --error-on-zero-trap"
},
{
"path": "sw/basic-gcov/test-ignore",
"chars": 0,
"preview": ""
},
{
"path": "sw/basic-gpio/Makefile",
"chars": 249,
"preview": "OBJECTS = bootstrap.o main.o uart.o\nCFLAGS = -g3 -march=rv32i -mabi=ilp32\nLDLIBS = -Tlink.ld -nostartfiles -Wl,--no"
},
{
"path": "sw/basic-gpio/bootstrap.S",
"chars": 942,
"preview": ".globl _start\n.globl main\n\n.equ SYSCALL_ADDR, 0x02010000\n\n.macro INIT_HW_PLATFORM\nand x1,x0,x0\nand x2,x0,x0\nand x3,x0,x0"
},
{
"path": "sw/basic-gpio/gpio.h",
"chars": 51,
"preview": "#ifndef GPIO_H\n#define GPIO_H\n\n\n#endif /* GPIO_H */"
},
{
"path": "sw/basic-gpio/link.ld",
"chars": 272,
"preview": "OUTPUT_ARCH( \"riscv\" )\nENTRY(_start)\n\nSECTIONS\n{\n . = 0x80000000;\n .text.init : { *(.text.init) }\n . = ALIGN(0x1000);"
},
{
"path": "sw/basic-gpio/main.c",
"chars": 730,
"preview": "#include <stdint.h>\n#include <stdio.h>\n#include \"platform.h\"\n#include \"uart.h\"\n#include \"util.h\"\n//#include \"gpio.h\"\nvoi"
},
{
"path": "sw/basic-gpio/platform.h",
"chars": 1428,
"preview": "#ifndef PLATFORM_H\n#define PLATFORM_H\n\n//#define MICRORV\n\n#ifdef MICRORV\n// LED\nstatic volatile uint32_t *LED_ADDR = (ui"
},
{
"path": "sw/basic-gpio/uart.c",
"chars": 848,
"preview": "#include \"uart.h\"\n#include \"platform.h\"\n#include <stdint.h>\n\nint sendString(char* str, long len) {\n\tlong cnt = len;\n\tcon"
},
{
"path": "sw/basic-gpio/uart.h",
"chars": 118,
"preview": "#ifndef UART_H\n\n#include <stdint.h>\n\nint sendString(char* str, long len);\nvoid putChr(char chr);\n\n#endif /* UART_H */"
},
{
"path": "sw/basic-gpio/util.c",
"chars": 1203,
"preview": "/*\n* utility functions for embedded usage where c-libs are too big\n*/\n\n//----------------------------\n// integer to asci"
},
{
"path": "sw/basic-gpio/util.h",
"chars": 156,
"preview": "#ifndef UTIL_H\n\nvoid swap(char *x, char *y);\nchar* reverse(char *buffer, int i, int j);\nchar* itoa(int value, char* buf"
},
{
"path": "sw/basic-multicore/Makefile",
"chars": 202,
"preview": "OBJECTS = main.o bootstrap.o\nCFLAGS = -march=rv32ima -mabi=ilp32\nLDFLAGS = -nostartfiles -Wl,--no-relax\n\nVP = "
},
{
"path": "sw/basic-multicore/bootstrap.S",
"chars": 1054,
"preview": ".globl _start\n.globl main\n\n.equ SYSCALL_ADDR, 0x02010000\n\n# NOTE: this will exit the whole simulation, i.e. stop all har"
},
{
"path": "sw/basic-multicore/main.c",
"chars": 142,
"preview": "int main(unsigned hart_id) {\n\t// behave differently based on the core (i.e. hart) id\n\tfor (unsigned i=0; i<100*hart_id; "
},
{
"path": "sw/blocking-sleep/Makefile",
"chars": 165,
"preview": "OBJECTS = main.o irq.o bootstrap.o\nCFLAGS = -march=rv32imac -mabi=ilp32\nLDFLAGS = -nostartfiles -Wl,--no-relax\n\nVP "
},
{
"path": "sw/blocking-sleep/bootstrap.S",
"chars": 174,
"preview": ".globl _start\n.globl register_handler\n.globl main\n\n_start:\ncall register_handler\njal main\n\n# call exit (SYS_EXIT=93) wit"
},
{
"path": "sw/blocking-sleep/irq.S",
"chars": 1310,
"preview": ".globl register_handler\n.globl lvl0_handler\n\n.align 4\nlvl0_handler:\n # Store all register values on the stack\n add"
},
{
"path": "sw/blocking-sleep/main.c",
"chars": 1181,
"preview": "#include <stdint.h>\n#include <stdbool.h>\n\nenum {\n\tSLEEP_TIME = 5, // In seconds\n\tUS_PER_SEC = 1000000,\n};\n\n/* This is us"
},
{
"path": "sw/busy-wait-sleep/Makefile",
"chars": 156,
"preview": "OBJECTS = main.o bootstrap.o\nCFLAGS = -march=rv32i -mabi=ilp32\nLDFLAGS = -nostartfiles -Wl,--no-relax\n\nVP = ti"
},
{
"path": "sw/busy-wait-sleep/bootstrap.S",
"chars": 128,
"preview": ".globl _start\n.globl main\n\n_start:\njal main\n\n# call exit (SYS_EXIT=93) with exit code 0 (argument in a0)\nli a7,93\nli a0,"
},
{
"path": "sw/busy-wait-sleep/main.c",
"chars": 512,
"preview": "#include <stdint.h>\n\nstatic volatile uint64_t *MTIMECMP_REG = (uint64_t *)0x2004000;\nstatic volatile uint64_t *MTIME_REG"
},
{
"path": "sw/c++-lib/Makefile",
"chars": 135,
"preview": "LD = $(CXX)\nOBJECTS = main.o\nCXXFLAGS = -std=c++14 -march=rv32imac -mabi=ilp32\n\ninclude ../Makefile.common\noverri"
},
{
"path": "sw/c++-lib/main.cpp",
"chars": 549,
"preview": "#include <iostream>\n#include <list>\n#include <map>\n#include <vector>\n\nstruct A {\n\tint a;\n\tint b;\n\n\tA(int a, int b) : a(a"
},
{
"path": "sw/clock-ticks/Makefile",
"chars": 143,
"preview": "OBJECTS = main.o irq.o bootstrap.o\nCFLAGS = -march=rv32imac -mabi=ilp32\nLDFLAGS = -nostartfiles -Wl,--no-relax\n\nincl"
},
{
"path": "sw/clock-ticks/bootstrap.S",
"chars": 1704,
"preview": ".globl _start\n.globl main\n.globl level_1_interrupt_handler\n\n_start:\nla t0, level_0_interrupt_handler\ncsrw mtvec, t0\nli t"
},
{
"path": "sw/clock-ticks/irq.c",
"chars": 2058,
"preview": "#include \"irq.h\"\n#include \"assert.h\"\n\n\n#define RISCV_MACHINE_SOFTWARE_INTERRUPT 3\n#define RISCV_MACHINE_TIMER_INTERRUPT "
},
{
"path": "sw/clock-ticks/irq.h",
"chars": 312,
"preview": "#ifndef __RISCV_IRQ_H__\n#define __RISCV_IRQ_H__\n\n#include \"stdint.h\"\n\ntypedef void (*irq_handler_t)(void);\n\nvoid registe"
},
{
"path": "sw/clock-ticks/main.c",
"chars": 615,
"preview": "#include \"stdint.h\"\n#include \"irq.h\"\n#include \"stdio.h\"\n#include \"assert.h\"\n\nstatic void set_next_timer_interrupt() {\n\ta"
},
{
"path": "sw/crc8/Makefile",
"chars": 235,
"preview": "OBJECTS = main.o uart.o bootstrap.o\nCFLAGS = -march=rv32i -mabi=ilp32\nLDFLAGS = -nostartfiles -Wl,--no-relax -T link"
},
{
"path": "sw/crc8/bootstrap.S",
"chars": 772,
"preview": ".globl _start\n.globl main\n\n.equ SYSCALL_ADDR, 0x02010000\n\n.macro INIT_HW_PLATFORM\nand x1,x0,x0\nand x2,x0,x0\nand x3,x0,x0"
},
{
"path": "sw/crc8/link.ld",
"chars": 272,
"preview": "OUTPUT_ARCH( \"riscv\" )\nENTRY(_start)\n\nSECTIONS\n{\n . = 0x80000000;\n .text.init : { *(.text.init) }\n . = ALIGN(0x1000);"
},
{
"path": "sw/crc8/main.c",
"chars": 2021,
"preview": "#include <stdint.h>\n#include <stdio.h>\n#include \"platform.h\"\n#include \"uart.h\"\n#include \"util.h\"\n\n// 8-bit SAE J1850 CRC"
},
{
"path": "sw/crc8/platform.h",
"chars": 884,
"preview": "#ifndef PLATFORM_H\n#define PLATFORM_H\n\n//#define MICRORV\n\n#ifdef MICRORV\n// LED\nstatic volatile uint32_t *LED_ADDR = (ui"
},
{
"path": "sw/crc8/uart.c",
"chars": 833,
"preview": "#include \"uart.h\"\n#include \"platform.h\"\n#include <stdint.h>\n\nint sendString(char* str, long len) {\n\tlong cnt = len;\n\tcon"
},
{
"path": "sw/crc8/uart.h",
"chars": 118,
"preview": "#ifndef UART_H\n\n#include <stdint.h>\n\nint sendString(char* str, long len);\nvoid putChr(char chr);\n\n#endif /* UART_H */"
},
{
"path": "sw/crc8/util.c",
"chars": 1203,
"preview": "/*\n* utility functions for embedded usage where c-libs are too big\n*/\n\n//----------------------------\n// integer to asci"
},
{
"path": "sw/crc8/util.h",
"chars": 156,
"preview": "#ifndef UTIL_H\n\nvoid swap(char *x, char *y);\nchar* reverse(char *buffer, int i, int j);\nchar* itoa(int value, char* buf"
},
{
"path": "sw/flashTest/Makefile",
"chars": 122,
"preview": "OBJECTS = main.o\nCXXFLAGS = -ggdb -std=c++14 -march=rv32ima -mabi=ilp32\n\ninclude ../Makefile.common\noverride LD = $(CXX"
},
{
"path": "sw/flashTest/main.cpp",
"chars": 1846,
"preview": "#include <inttypes.h>\n#include <string.h>\n#include <iostream>\n\n// From flash.h\nstatic constexpr unsigned int BLOCKSIZE ="
},
{
"path": "sw/flashTest/test-ignore",
"chars": 0,
"preview": ""
},
{
"path": "sw/mramTest/Makefile",
"chars": 122,
"preview": "OBJECTS = main.o\nCXXFLAGS = -ggdb -std=c++14 -march=rv32ima -mabi=ilp32\n\ninclude ../Makefile.common\noverride LD = $(CXX"
},
{
"path": "sw/mramTest/main.cpp",
"chars": 693,
"preview": "#include <string.h>\n#include \"stdio.h\"\n\nstatic char* const MRAM_START_ADDR = reinterpret_cast<char* const>(0x60000000);\n"
},
{
"path": "sw/mrv32-uart/Makefile",
"chars": 254,
"preview": "rvArch?=rv32i\n\nOBJECTS = bootstrap.o main.o uart.o util.o\nCFLAGS = -march=$(rvArch) -mabi=ilp32 -mno-strict-align\nLDF"
},
{
"path": "sw/mrv32-uart/bootstrap.S",
"chars": 859,
"preview": ".globl _start\n.globl main\n\n.equ SYSCALL_ADDR, 0x02010000\n\n.macro INIT_HW_PLATFORM\nand x1,x0,x0\nand x2,x0,x0\nand x3,x0,x0"
},
{
"path": "sw/mrv32-uart/link.ld",
"chars": 360,
"preview": "OUTPUT_ARCH( \"riscv\" )\nENTRY(_start)\n\nMEMORY {\n RAM (rwx): ORIGIN = 0x80000000, LENGTH = 8k\n}\n\nSECTIONS\n{\n . = 0x80000"
},
{
"path": "sw/mrv32-uart/main.c",
"chars": 777,
"preview": "#include <stdint.h>\n#include <stdio.h>\n// #include <string.h>\n#include \"platform.h\"\n#include \"uart.h\"\n#include \"util.h\"\n"
},
{
"path": "sw/mrv32-uart/platform.h",
"chars": 1405,
"preview": "#ifndef PLATFORM_H\n#define PLATFORM_H\n\n/* #define MICRORV\n\n// #ifdef MICRORV */\n// LED\nstatic volatile uint32_t *LED_ADD"
},
{
"path": "sw/mrv32-uart/uart.c",
"chars": 519,
"preview": "#include \"uart.h\"\n#include \"platform.h\"\n#include <stdint.h>\n\nint sendString(char* str, long len) {\n\tlong cnt = len;\n\tcon"
},
{
"path": "sw/mrv32-uart/uart.h",
"chars": 118,
"preview": "#ifndef UART_H\n\n#include <stdint.h>\n\nint sendString(char* str, long len);\nvoid putChr(char chr);\n\n#endif /* UART_H */"
},
{
"path": "sw/mrv32-uart/util.c",
"chars": 1203,
"preview": "/*\n* utility functions for embedded usage where c-libs are too big\n*/\n\n//----------------------------\n// integer to asci"
},
{
"path": "sw/mrv32-uart/util.h",
"chars": 156,
"preview": "#ifndef UTIL_H\n\nvoid swap(char *x, char *y);\nchar* reverse(char *buffer, int i, int j);\nchar* itoa(int value, char* buf"
},
{
"path": "sw/peripheral-in-the-loop/Makefile",
"chars": 892,
"preview": "OBJECTS = main.o irq.o bootstrap.o\nCFLAGS = -march=rv32i -mabi=ilp32\nLDFLAGS = -nostartfiles -Wl,--no-relax\n\nvirtual-bu"
},
{
"path": "sw/peripheral-in-the-loop/main.c",
"chars": 1424,
"preview": "#include <stdint.h>\n#include \"../simple-sensor/irq.h\"\n\ntypedef uint32_t BUS_BRIDGE_TYPE;\nstatic volatile BUS_BRIDGE_TYPE"
},
{
"path": "sw/printf/Makefile",
"chars": 165,
"preview": "OBJECTS = main.o entry.o\nCFLAGS = -march=rv32i -mabi=ilp32\nLDFLAGS = -Wl,-e_reset_vector\nVP_FLAGS = --error-on-zero-"
},
{
"path": "sw/printf/entry.S",
"chars": 249,
"preview": ".globl _start\n.globl _reset_vector\n.equ SYSCALL_ADDR, 0x02010000\n\ntrap_handler:\n\tli t0, SYSCALL_ADDR\n\tcsrr t1, mhartid"
},
{
"path": "sw/printf/main.c",
"chars": 419,
"preview": "#include \"stdio.h\"\n#include \"errno.h\"\n#include \"string.h\"\n#include \"unistd.h\"\n\nint main(int argc, char **argv) {\n\tint n "
},
{
"path": "sw/simple-display/Makefile",
"chars": 181,
"preview": "OBJECTS = main.o libDisplay.o\nCXXFLAGS = -std=c++14 -march=rv32ima -mabi=ilp32\n\nremoveSHMEM:\n\tipcrm --shmem-key 0x00000"
},
{
"path": "sw/simple-display/libDisplay.cpp",
"chars": 1922,
"preview": "/*\n * libDisplay.cpp\n *\n * Created on: Oct 5, 2018\n * Author: dwd\n */\n\n#include \"libDisplay.hpp\"\n#include <math.h>"
},
{
"path": "sw/simple-display/libDisplay.hpp",
"chars": 985,
"preview": "/*\n * libDisplay.hpp\n *\n * Created on: Oct 5, 2018\n * Author: dwd\n */\n\n#pragma once\n\n#include \"../../env/basic/vp-"
},
{
"path": "sw/simple-display/main.cpp",
"chars": 3523,
"preview": "#include \"libDisplay.hpp\"\n\n#include <math.h>\n#include <climits>\n#include <cstring>\n#include <iostream>\n\nFramebuffer* vol"
},
{
"path": "sw/simple-display/test-ignore",
"chars": 0,
"preview": ""
},
{
"path": "sw/simple-scheduler/Makefile",
"chars": 91,
"preview": "OBJECTS = main.o cor.o\nCFLAGS = -march=rv32imac -mabi=ilp32\n\ninclude ../Makefile.common\n"
},
{
"path": "sw/simple-scheduler/cor.S",
"chars": 1480,
"preview": ".globl contextswitch\n.globl coroutine_entry\n.globl launch_coroutine\n\n\ncoroutine_entry:\n\t// move the launch argument to t"
},
{
"path": "sw/simple-scheduler/main.c",
"chars": 2016,
"preview": "#include <stdlib.h>\n#include <stdio.h>\n#include <assert.h>\n#include <stdint.h>\n\n#define REG_SP 1\n#define REG_S0 7\n\ntyped"
},
{
"path": "sw/simple-scheduler/no-clib/Makefile",
"chars": 283,
"preview": "all : main.c\n\triscv32-unknown-elf-gcc main.c cor.S bootstrap.S -o main -march=rv32ima -mabi=ilp32 -nostartfiles\n\nsim: al"
},
{
"path": "sw/simple-scheduler/no-clib/bootstrap.S",
"chars": 287,
"preview": ".globl _start\n.globl main\n\n\n_start:\n\n# Initialize global pointer\n.option push\n.option norelax\n1:auipc gp, %pcrel_hi(__gl"
},
{
"path": "sw/simple-scheduler/no-clib/cor.S",
"chars": 1921,
"preview": ".globl contextswitch\n.globl coroutine_entry\n.globl launch_coroutine\n\n\ncoroutine_entry:\n\t// move the launch argument to t"
},
{
"path": "sw/simple-scheduler/no-clib/main.c",
"chars": 1997,
"preview": "#include \"stdlib.h\"\n#include \"stdio.h\"\n#include \"assert.h\"\n\n\n#define REG_SP 1\n#define REG_S0 7\n\ntypedef void (*entrypoin"
},
{
"path": "sw/simple-sensor/Makefile",
"chars": 140,
"preview": "OBJECTS = main.o irq.o bootstrap.o\nCFLAGS = -march=rv32i -mabi=ilp32\nLDFLAGS = -nostartfiles -Wl,--no-relax\n\ninclude"
},
{
"path": "sw/simple-sensor/bootstrap.S",
"chars": 2202,
"preview": ".globl _start\n.globl main\n.globl level_1_interrupt_handler\n\n.equ SYSCALL_ADDR, 0x02010000\n.equ PLIC_ENABLED_IRQ_ADDR, 0x"
},
{
"path": "sw/simple-sensor/irq.c",
"chars": 2058,
"preview": "#include \"irq.h\"\n#include \"assert.h\"\n\n\n#define RISCV_MACHINE_SOFTWARE_INTERRUPT 3\n#define RISCV_MACHINE_TIMER_INTERRUPT "
},
{
"path": "sw/simple-sensor/irq.h",
"chars": 312,
"preview": "#ifndef __RISCV_IRQ_H__\n#define __RISCV_IRQ_H__\n\n#include \"stdint.h\"\n\ntypedef void (*irq_handler_t)(void);\n\nvoid registe"
},
{
"path": "sw/simple-sensor/main.c",
"chars": 856,
"preview": "#include <stdint.h>\n#include \"irq.h\"\n\nstatic volatile char * const TERMINAL_ADDR = (char * const)0x20000000;\nstatic vola"
},
{
"path": "sw/sys-read/Makefile",
"chars": 84,
"preview": "OBJECTS = main.o\nCFLAGS = -march=rv32ima -mabi=ilp32\n\ninclude ../Makefile.common\n"
},
{
"path": "sw/sys-read/main.c",
"chars": 305,
"preview": "#include \"stdio.h\"\n\nint main(int argc, char **argv) {\n\tprintf(\"Enter a number: \");\n\n\tint c,n = 0;\n\twhile (!scanf(\"%d\", &"
},
{
"path": "sw/sys-read/test-ignore",
"chars": 0,
"preview": ""
},
{
"path": "sw/test.sh",
"chars": 456,
"preview": "#!/bin/sh\n\nexport SYSTEMC_DISABLE_COPYRIGHT_MESSAGE=1\n\nhandle_exit() {\n\t[ $# -eq 1 ] || exit 1\n\n\tif [ \"${1}\" -eq 0 ]; th"
},
{
"path": "vp/.gitignore",
"chars": 6,
"preview": "build\n"
},
{
"path": "vp/CMakeLists.txt",
"chars": 1448,
"preview": "cmake_minimum_required(VERSION 3.18)\nproject(riscv-vp\n\tVERSION 1.2.2\n)\n\noption(USE_SYSTEM_SYSTEMC \"use systemc version p"
},
{
"path": "vp/cmake/AddGitSubmodule.cmake",
"chars": 816,
"preview": "#thanks @ https://gist.github.com/scivision/bb1d47a9529e153617414e91ff5390af\n\ncmake_minimum_required(VERSION 3.16)\n\nfunc"
},
{
"path": "vp/src/CMakeLists.txt",
"chars": 72,
"preview": "include_directories(.)\n\nsubdirs(vendor)\nsubdirs(core)\nsubdirs(platform)\n"
},
{
"path": "vp/src/core/CMakeLists.txt",
"chars": 44,
"preview": "subdirs(common)\nsubdirs(rv32)\nsubdirs(rv64)\n"
},
{
"path": "vp/src/core/common/CMakeLists.txt",
"chars": 333,
"preview": "file(GLOB_RECURSE HEADERS ${CMAKE_CURRENT_SOURCE_DIR}/*.h)\n\nadd_library(core-common\n\t\ttimer.cpp\n\t\treal_clint.cpp\n\t\tinstr"
},
{
"path": "vp/src/core/common/bus_lock_if.h",
"chars": 421,
"preview": "#pragma once\n\nstruct bus_lock_if {\n virtual ~bus_lock_if() {}\n\n\tvirtual void lock(unsigned hart_id) = 0;\n\n\tvirtual vo"
},
{
"path": "vp/src/core/common/clint.h",
"chars": 4514,
"preview": "#ifndef RISCV_ISA_CLINT_H\n#define RISCV_ISA_CLINT_H\n\n#include \"clint_if.h\"\n#include \"irq_if.h\"\n\n#include <tlm_utils/simp"
},
{
"path": "vp/src/core/common/clint_if.h",
"chars": 126,
"preview": "#pragma once\n\n#include <stdint.h>\n\nstruct clint_if {\n\tvirtual ~clint_if() {}\n\n\tvirtual uint64_t update_and_get_mtime() ="
},
{
"path": "vp/src/core/common/core_defs.h",
"chars": 379,
"preview": "#pragma once\n\nenum Architecture {\n\tRV32 = 1,\n\tRV64 = 2,\n\tRV128 = 3,\n};\n\nenum class CoreExecStatus {\n\tRunnable,\n\tHitBreak"
},
{
"path": "vp/src/core/common/debug.h",
"chars": 770,
"preview": "#ifndef RISCV_DEBUG\n#define RISCV_DEBUG\n\n#include <stdint.h>\n\n#include <unordered_set>\n#include <vector>\n\n#include \"core"
},
{
"path": "vp/src/core/common/debug_memory.cpp",
"chars": 2309,
"preview": "#include \"debug_memory.h\"\n\n#include <assert.h>\n#include <stdio.h>\n#include <stdint.h>\n#include <stdlib.h>\n#include <errn"
},
{
"path": "vp/src/core/common/debug_memory.h",
"chars": 671,
"preview": "#ifndef RISCV_ISA_DEBUG_MEMORY_H\n#define RISCV_ISA_DEBUG_MEMORY_H\n\n#include <string>\n#include <type_traits>\n\n#include <t"
},
{
"path": "vp/src/core/common/dmi.h",
"chars": 1808,
"preview": "#pragma once\n\n#include <stdint.h>\n\nclass MemoryDMI {\n\tuint8_t *mem;\n\tuint64_t start;\n\tuint64_t size;\n\tuint64_t end;\n\n\tMe"
},
{
"path": "vp/src/core/common/elf_loader.h",
"chars": 6285,
"preview": "#pragma once\n\n#include <boost/iostreams/device/mapped_file.hpp>\n#include <exception>\n#include <cstdint>\n#include <vector"
},
{
"path": "vp/src/core/common/fp.h",
"chars": 2277,
"preview": "#pragma once\n\n#include <softfloat/softfloat.hpp>\n\n// floating-point rounding modes\nconstexpr unsigned FRM_RNE = 0b000; "
},
{
"path": "vp/src/core/common/gdb-mc/CMakeLists.txt",
"chars": 167,
"preview": "add_subdirectory(libgdb)\n\nadd_library(gdb-mc\n\tgdb_server.cpp\n\tgdb_runner.cpp\n\tregister_format.cpp\n\thandler.cpp)\n\ntarget_"
},
{
"path": "vp/src/core/common/gdb-mc/gdb_runner.cpp",
"chars": 691,
"preview": "#include \"gdb_runner.h\"\n\nGDBServerRunner::GDBServerRunner(sc_core::sc_module_name name, GDBServer *server, debug_target_"
},
{
"path": "vp/src/core/common/gdb-mc/gdb_runner.h",
"chars": 406,
"preview": "#ifndef RISCV_GDB_RUNNER\n#define RISCV_GDB_RUNNER\n\n#include <systemc>\n\n#include \"debug.h\"\n#include \"gdb_server.h\"\n\nSC_MO"
},
{
"path": "vp/src/core/common/gdb-mc/gdb_server.cpp",
"chars": 7433,
"preview": "#include <err.h>\n#include <assert.h>\n#include <stdio.h>\n#include <string.h>\n#include <unistd.h>\n#include <stdint.h>\n#inc"
},
{
"path": "vp/src/core/common/gdb-mc/gdb_server.h",
"chars": 2816,
"preview": "#ifndef RISCV_GDB_NG\n#define RISCV_GDB_NG\n\n#include <stdint.h>\n#include <stddef.h>\n#include <stdbool.h>\n\n#include <queue"
},
{
"path": "vp/src/core/common/gdb-mc/handler.cpp",
"chars": 8665,
"preview": "#include <assert.h>\n#include <stdlib.h>\n#include <limits.h>\n\n#include <libgdb/parser2.h>\n\n#include \"debug.h\"\n#include \"g"
},
{
"path": "vp/src/core/common/gdb-mc/libgdb/CMakeLists.txt",
"chars": 452,
"preview": "add_library(gdb\n\tmpc/mpc.c\n\tparser1.c\n\tparser2.c\n\tresponse.c\n\tutil.c)\n\ntarget_compile_options(gdb PRIVATE\n\t-Wpedantic -W"
},
{
"path": "vp/src/core/common/gdb-mc/libgdb/README.md",
"chars": 1460,
"preview": "# libgdb\n\nUtility library for implementing the [GDB protocol][gdb protocol].\n\n## Design\n\nUnfortunately, the GDB protocol"
},
{
"path": "vp/src/core/common/gdb-mc/libgdb/include/libgdb/parser1.h",
"chars": 476,
"preview": "#ifndef LIBGDB_PARSER1_H\n#define LIBGDB_PARSER1_H\n\n#ifdef __cplusplus\nextern \"C\" {\n#endif\n\n#include <stdio.h>\n#include <"
},
{
"path": "vp/src/core/common/gdb-mc/libgdb/include/libgdb/parser2.h",
"chars": 1685,
"preview": "#ifndef LIBGDB_PARSER2_H\n#define LIBGDB_PARSER2_H\n\n#ifdef __cplusplus\nextern \"C\" {\n#endif\n\n#include <stddef.h>\n#include "
},
{
"path": "vp/src/core/common/gdb-mc/libgdb/include/libgdb/response.h",
"chars": 503,
"preview": "#ifndef LIBGDB_RESPONSE_H\n#define LIBGDB_RESPONSE_H\n\n#ifdef __cplusplus\nextern \"C\" {\n#endif\n\n/* Copied from QEMU\n * See:"
},
{
"path": "vp/src/core/common/gdb-mc/libgdb/internal.h",
"chars": 517,
"preview": "#ifndef GDB_PROTOCOL_FNS\n#define GDB_PROTOCOL_FNS\n\n#include <assert.h>\n#include <stddef.h>\n\n#include <libgdb/parser2.h>\n"
},
{
"path": "vp/src/core/common/gdb-mc/libgdb/parser1.c",
"chars": 2285,
"preview": "#include <stdio.h>\n#include <stdlib.h>\n#include <stdint.h>\n\n#include <libgdb/parser1.h>\n\n#include \"mpc.h\"\n#include \"inte"
},
{
"path": "vp/src/core/common/gdb-mc/libgdb/parser2.c",
"chars": 6976,
"preview": "#include <errno.h>\n#include <stdlib.h>\n#include <string.h>\n\n#include <libgdb/parser1.h>\n#include <libgdb/parser2.h>\n\n#in"
},
{
"path": "vp/src/core/common/gdb-mc/libgdb/parser2.h",
"chars": 4733,
"preview": "#define gdbf_fold(I, TYPE, FUNC) \\\n\tstatic mpc_val_t *gdbf_packet_##I(int "
},
{
"path": "vp/src/core/common/gdb-mc/libgdb/response.c",
"chars": 1176,
"preview": "#include <err.h>\n#include <stdlib.h>\n#include <stddef.h>\n#include <string.h>\n#include <stdio.h>\n\n#include <libgdb/parser"
},
{
"path": "vp/src/core/common/gdb-mc/libgdb/util.c",
"chars": 3077,
"preview": "#include <err.h>\n#include <limits.h>\n#include <stdio.h>\n#include <string.h>\n#include <stddef.h>\n#include <stdbool.h>\n#in"
},
{
"path": "vp/src/core/common/gdb-mc/register_format.cpp",
"chars": 557,
"preview": "#include <iomanip>\n\n#include <byteswap.h>\n\n#include \"register_format.h\"\n\nRegisterFormater::RegisterFormater(Architecture"
},
{
"path": "vp/src/core/common/gdb-mc/register_format.h",
"chars": 315,
"preview": "#ifndef RISCV_GDB_REGISTER\n#define RISCV_GDB_REGISTER\n\n#include <sstream>\n\n#include <stdint.h>\n\n#include \"core_defs.h\"\n\n"
},
{
"path": "vp/src/core/common/instr.cpp",
"chars": 58219,
"preview": "#include \"instr.h\"\n#include \"trap.h\"\n#include \"util/common.h\"\n\n#include <cassert>\n#include <stdexcept>\n\nconstexpr uint32"
},
{
"path": "vp/src/core/common/instr.h",
"chars": 11060,
"preview": "#ifndef RISCV_ISA_INSTR_H\n#define RISCV_ISA_INSTR_H\n\n#include <stdint.h>\n#include <array>\n#include <iostream>\n\n#include "
},
{
"path": "vp/src/core/common/irq_if.h",
"chars": 942,
"preview": "#ifndef RISCV_ISA_IRQ_IF_H\n#define RISCV_ISA_IRQ_IF_H\n\n#include <stdint.h>\n\ntypedef uint32_t PrivilegeLevel;\n\nconstexpr "
},
{
"path": "vp/src/core/common/load_if.h",
"chars": 266,
"preview": "#ifndef RISCV_VP_LOAD_IF_H\n#define RISCV_VP_LOAD_IF_H\n\n#include <stdint.h>\n#include <stddef.h>\n\nclass load_if {\n public"
},
{
"path": "vp/src/core/common/mmu.h",
"chars": 8109,
"preview": "#pragma once\n\n#include \"mmu_mem_if.h\"\n\nconstexpr unsigned PTE_PPN_SHIFT = 10;\nconstexpr unsigned PGSHIFT = 12;\nconstexpr"
},
{
"path": "vp/src/core/common/mmu_mem_if.h",
"chars": 470,
"preview": "#ifndef RISCV_VP_MMU_MEM_IF_H\n#define RISCV_VP_MMU_MEM_IF_H\n\n#include <stdint.h>\n\nenum MemoryAccessType { FETCH, LOAD, S"
},
{
"path": "vp/src/core/common/rawmode.cpp",
"chars": 3928,
"preview": "/* Copied from linenoise <https://github.com/antirez/linenoise> with slight modifications.\n *\n * Copyright (c) 2019, Sör"
},
{
"path": "vp/src/core/common/rawmode.h",
"chars": 114,
"preview": "#ifndef RISCV_VP_RAWMODE_H\n#define RISCV_VP_RAWMODE_H\n\nvoid enableRawMode(int);\nvoid disableRawMode(int);\n\n#endif\n"
},
{
"path": "vp/src/core/common/real_clint.cpp",
"chars": 3968,
"preview": "#include <assert.h>\n#include <stddef.h>\n\n#include \"real_clint.h\"\n\nenum {\n\tMSIP_BASE = 0,\n\tMSIP_SIZE = 4,\n\n\tMTIMECMP_BASE"
},
{
"path": "vp/src/core/common/real_clint.h",
"chars": 1870,
"preview": "#ifndef RISCV_VP_REAL_CLINT_H\n#define RISCV_VP_REAL_CLINT_H\n\n#include <stdint.h>\n\n#include <chrono>\n#include <systemc>\n#"
},
{
"path": "vp/src/core/common/timer.cpp",
"chars": 2955,
"preview": "#include <assert.h>\n#include <limits.h>\n#include <stdlib.h>\n#include <signal.h>\n#include <errno.h>\n#include <err.h>\n\n#in"
},
{
"path": "vp/src/core/common/timer.h",
"chars": 653,
"preview": "#ifndef RISCV_VP_TIMER_H\n#define RISCV_VP_TIMER_H\n\n#include <chrono>\n#include <system_error>\n\n#include <stdint.h>\n#inclu"
},
{
"path": "vp/src/core/common/trap.h",
"chars": 965,
"preview": "#pragma once\n\nenum ExceptionCode {\n\t// interrupt exception codes (mcause)\n\tEXC_U_SOFTWARE_INTERRUPT = 0,\n\tEXC_S_SOFTWARE"
},
{
"path": "vp/src/core/rv32/CMakeLists.txt",
"chars": 523,
"preview": "file(GLOB_RECURSE HEADERS ${CMAKE_CURRENT_SOURCE_DIR}/*.h)\n\nadd_library(rv32\n\t\tiss.cpp\n\t\tsyscall.cpp\n ${HEADERS})"
},
{
"path": "vp/src/core/rv32/csr.h",
"chars": 27048,
"preview": "#pragma once\n\n#include <assert.h>\n#include <stdint.h>\n\n#include <stdexcept>\n#include <unordered_map>\n\n#include \"core/com"
},
{
"path": "vp/src/core/rv32/elf_loader.h",
"chars": 1799,
"preview": "#pragma once\n\n#include \"core/common/elf_loader.h\"\n\nnamespace rv32 {\n\n// see: http://wiki.osdev.org/ELF_Tutorial for ELF "
},
{
"path": "vp/src/core/rv32/iss.cpp",
"chars": 52961,
"preview": "#include \"iss.h\"\n\n// to save *cout* format setting, see *ISS::show*\n#include <boost/io/ios_state.hpp>\n// for safe down-c"
},
{
"path": "vp/src/core/rv32/iss.h",
"chars": 8124,
"preview": "#pragma once\n\n#include \"core/common/bus_lock_if.h\"\n#include \"core/common/clint_if.h\"\n#include \"core/common/instr.h\"\n#inc"
},
{
"path": "vp/src/core/rv32/mem.h",
"chars": 6277,
"preview": "#pragma once\n\n#include \"core/common/dmi.h\"\n#include \"iss.h\"\n#include \"mmu.h\"\n\nnamespace rv32 {\n\n/* For optimization, use"
},
{
"path": "vp/src/core/rv32/mem_if.h",
"chars": 1181,
"preview": "#pragma once\n\n#include <stdint.h>\n\nnamespace rv32 {\n\nstruct instr_memory_if {\n\tvirtual ~instr_memory_if() {}\n\n\tvirtual u"
},
{
"path": "vp/src/core/rv32/mmu.h",
"chars": 133,
"preview": "#pragma once\n\n#include \"iss.h\"\n#include \"core/common/mmu.h\"\n\nnamespace rv32 {\n\n typedef GenericMMU<ISS> MMU;\n\n} // n"
},
{
"path": "vp/src/core/rv32/syscall.cpp",
"chars": 6643,
"preview": "#include \"syscall.h\"\n\n#include <assert.h>\n#include <sys/stat.h>\n#include <sys/time.h>\n#include <sys/types.h>\n#include <u"
},
{
"path": "vp/src/core/rv32/syscall.h",
"chars": 4209,
"preview": "#pragma once\n\n#include <assert.h>\n#include <fcntl.h>\n#include <stdint.h>\n\n#include <boost/lexical_cast.hpp>\n\n// see: new"
},
{
"path": "vp/src/core/rv32/syscall_if.h",
"chars": 694,
"preview": "#pragma once\n\n#include <stdint.h>\n\nnamespace rv32 {\n\n/* The syscall handler is using this interface to access and contro"
},
{
"path": "vp/src/core/rv32/timing/timing_external.h",
"chars": 1920,
"preview": "#pragma once\n\n#include \"../iss.h\"\n\n#include <dlfcn.h>\n#include <boost/io/ios_state.hpp>\n#include <iomanip>\n\nstd::string "
},
{
"path": "vp/src/core/rv32/timing/timing_simple.h",
"chars": 1429,
"preview": "#pragma once\n\n#include \"../iss.h\"\n\nstruct SimpleTimingDecorator : public timing_if {\n\tstd::array<sc_core::sc_time, Opcod"
},
{
"path": "vp/src/core/rv64/CMakeLists.txt",
"chars": 523,
"preview": "file(GLOB_RECURSE HEADERS ${CMAKE_CURRENT_SOURCE_DIR}/*.h)\n\nadd_library(rv64\n\t\tiss.cpp\n\t\tsyscall.cpp\n ${HEADERS})"
},
{
"path": "vp/src/core/rv64/csr.h",
"chars": 23462,
"preview": "#pragma once\n\n#include <assert.h>\n#include <stdint.h>\n\n#include <stdexcept>\n#include <unordered_map>\n\n#include \"core/com"
},
{
"path": "vp/src/core/rv64/elf_loader.h",
"chars": 3081,
"preview": "#pragma once\n\n#include \"core/common/elf_loader.h\"\n\nnamespace rv64 {\n\n// see: \"ELF-64 Object File Format\" document for EL"
},
{
"path": "vp/src/core/rv64/iss.cpp",
"chars": 51608,
"preview": "#include \"iss.h\"\n\n// to save *cout* format setting, see *ISS::show*\n#include <boost/format.hpp>\n#include <boost/io/ios_s"
},
{
"path": "vp/src/core/rv64/iss.h",
"chars": 8168,
"preview": "#pragma once\n\n#include \"core/common/bus_lock_if.h\"\n#include \"core/common/clint_if.h\"\n#include \"core/common/core_defs.h\"\n"
},
{
"path": "vp/src/core/rv64/mem.h",
"chars": 7264,
"preview": "#pragma once\n\n#include \"core/common/dmi.h\"\n#include \"iss.h\"\n#include \"mmu.h\"\n\nnamespace rv64 {\n\n/* For optimization, use"
},
{
"path": "vp/src/core/rv64/mem_if.h",
"chars": 1430,
"preview": "#pragma once\n\n#include <stdint.h>\n\nnamespace rv64 {\n\nstruct instr_memory_if {\n\tvirtual ~instr_memory_if() {}\n\n\tvirtual u"
},
{
"path": "vp/src/core/rv64/mmu.h",
"chars": 133,
"preview": "#pragma once\n\n#include \"iss.h\"\n#include \"core/common/mmu.h\"\n\nnamespace rv64 {\n\n typedef GenericMMU<ISS> MMU;\n\n} // n"
},
{
"path": "vp/src/core/rv64/syscall.cpp",
"chars": 6461,
"preview": "#include \"syscall.h\"\n\n#include <assert.h>\n#include <sys/stat.h>\n#include <sys/time.h>\n#include <sys/types.h>\n#include <u"
},
{
"path": "vp/src/core/rv64/syscall.h",
"chars": 4111,
"preview": "#pragma once\n\n#include <assert.h>\n#include <fcntl.h>\n#include <stdint.h>\n\n// see: newlib/libgloss/riscv @\n// https://git"
},
{
"path": "vp/src/core/rv64/syscall_if.h",
"chars": 566,
"preview": "#pragma once\n\n#include <stdint.h>\n\nnamespace rv64 {\n\n/* The syscall handler is using this interface to access and contro"
},
{
"path": "vp/src/platform/CMakeLists.txt",
"chars": 192,
"preview": "file(GLOB sources_list LIST_DIRECTORIES true *)\nforeach(dir ${sources_list})\n IF(IS_DIRECTORY ${dir})\n add_sub"
},
{
"path": "vp/src/platform/basic/CMakeLists.txt",
"chars": 454,
"preview": "file(GLOB_RECURSE HEADERS ${CMAKE_CURRENT_SOURCE_DIR}/*.h)\n\nadd_library(platform-basic\nethernet.cpp\ndisplay.cpp\n${HEADER"
},
{
"path": "vp/src/platform/basic/basic_timer.h",
"chars": 586,
"preview": "#ifndef RISCV_ISA_BASIC_TIMER_H\n#define RISCV_ISA_BASIC_TIMER_H\n\n#include <systemc>\n\n#include <tlm_utils/simple_target_s"
},
{
"path": "vp/src/platform/basic/display.cpp",
"chars": 4692,
"preview": "/*\n * display.cpp\n *\n * Created on: Sep 11, 2018\n * Author: dwd\n */\n\n#include \"display.hpp\"\n#include <math.h>\n#inc"
},
{
"path": "vp/src/platform/basic/display.hpp",
"chars": 828,
"preview": "/*\n * display.hpp\n *\n * Created on: Sep 11, 2018\n * Author: dwd\n */\n\n#pragma once\n\n#include <tlm_utils/simple_targ"
},
{
"path": "vp/src/platform/basic/dma.h",
"chars": 3423,
"preview": "#ifndef RISCV_ISA_DMA_H\n#define RISCV_ISA_DMA_H\n\n#include <systemc>\n\n#include <tlm_utils/simple_initiator_socket.h>\n#inc"
},
{
"path": "vp/src/platform/basic/ethernet.cpp",
"chars": 9459,
"preview": "#include \"ethernet.h\"\n\n#include <netinet/ether.h>\n#include <netinet/in.h>\n#include <sys/socket.h>\n#include <sys/types.h>"
},
{
"path": "vp/src/platform/basic/ethernet.h",
"chars": 3306,
"preview": "#ifndef RISCV_VP_ETHERNET_H\n#define RISCV_VP_ETHERNET_H\n\n#include <unistd.h>\n#include <cstdlib>\n#include <cstring>\n#incl"
},
{
"path": "vp/src/platform/basic/flash.h",
"chars": 5178,
"preview": "#pragma once\n\n#include <fcntl.h>\n#include <linux/fs.h>\n#include <stdint.h>\n#include <sys/ioctl.h>\n#include <unistd.h> /"
}
]
// ... and 313 more files (download for full content)
About this extraction
This page contains the full source code of the agra-uni-bremen/riscv-vp GitHub repository, extracted and formatted as plain text for AI agents and large language models (LLMs). The extraction includes 513 files (1.5 MB), approximately 435.0k tokens, and a symbol index with 934 extracted functions, classes, methods, constants, and types. Use this with OpenClaw, Claude, ChatGPT, Cursor, Windsurf, or any other AI tool that accepts text input. You can copy the full output to your clipboard or download it as a .txt file.
Extracted by GitExtract — free GitHub repo to text converter for AI. Built by Nikandr Surkov.