Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
33 commits
Select commit Hold shift + click to select a range
8878686
add basic support for device cycle-simulator
Humber-186 Mar 23, 2025
028582e
basic support for chisel RTL verilator sim device
Humber-186 Mar 25, 2025
b18059e
some changes
Humber-186 May 27, 2025
3f40fde
bug fixed
Humber-186 Jun 11, 2025
ca1d37f
CMakeLists big changes
Humber-186 Jun 21, 2025
efdde0d
add auto-select driver interface
Humber-186 Jun 21, 2025
cb20950
add default libventus_driver.so
Humber-186 Jun 21, 2025
f7cd61c
bug fixed
Humber-186 Jun 21, 2025
de9bcfd
RTL device: use buddy allocator for physical memory management
Humber-186 Jul 20, 2025
4cd3f1c
cyclesim support vcd trace dump
Humber-186 Jul 22, 2025
b4729e7
fix: empty ENV CYCLESIM_WAVEFORM cause segment fault
Humber-186 Aug 9, 2025
d4103c3
feat: gvm basic
xwxthu Aug 24, 2025
c71e45c
add: BACKEND alias & logs
Humber-186 Aug 25, 2025
9cf9cad
add: dump copy_from_dev to json (VENTUS_DRIVER_DUMP_RESULT=filename.j…
Humber-186 Aug 25, 2025
bcbe9e7
feat: support multi kernel testcase.
xwxthu Sep 4, 2025
0495d1d
style: SPDLOG output improved
Humber-186 Sep 7, 2025
5ed3d41
add: support RTL icache invalidate from host
Humber-186 Sep 7, 2025
93067d5
add: get kernel name from POCL
Humber-186 Sep 12, 2025
bb0a56c
add: README
Humber-186 Sep 12, 2025
6718d15
clean: 移除无用文件,部分注释与重命名
Humber-186 Sep 12, 2025
c9f3355
Merge remote-tracking branch 'origin/dev-devices' into gvm
xwxthu Sep 15, 2025
69fbcab
fix: cyclesim ELF auto-alloc needs free
Humber-186 Sep 22, 2025
d789ae1
fix: CMake missing dep nlohmann_json
Humber-186 Oct 3, 2025
14bbb9c
feat(rtl): get hardware specification from backend (vt_dev_caps)
Humber-186 Oct 3, 2025
1e48d84
fix: return -1 for not-implemented vt_dev_caps
Humber-186 Oct 3, 2025
c6a0a9c
update gvm waveform
xwxthu Oct 3, 2025
9a97bf4
Merge remote-tracking branch 'origin/gvm' into dev-devices
xwxthu Oct 3, 2025
6cc5507
feat(cycle): add env var VENTUS_TIMING_DDR to enable/disable ramulato…
Humber-186 Oct 4, 2025
9a7be7e
add: rtl parameter in gvm
xwxthu Oct 4, 2025
95c07ba
Merge remote-tracking branch 'origin/dev-devices' into dev-devices
xwxthu Oct 4, 2025
8efb2f7
style(cycle): change default waveform file name
Humber-186 Oct 5, 2025
86a4860
add: English README
Humber-186 Oct 5, 2025
7615a87
fix(GVM): enable waveform generate.
xwxthu Nov 30, 2025
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
9 changes: 9 additions & 0 deletions .clang-format
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
BasedOnStyle: LLVM # 基于LLVM的代码风格
IndentWidth: 4 # 缩进宽度为4个空格
AccessModifierOffset: -4 # 访问修饰符的偏移量为-4
ColumnLimit: 100 # 每行代码的最大列数
AlwaysBreakAfterDefinitionReturnType: None
PenaltyReturnTypeOnItsOwnLine: 1000000
AlignAfterOpenBracket: BlockIndent
AllowShortIfStatementsOnASingleLine: true

4 changes: 3 additions & 1 deletion .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -9,4 +9,6 @@ test
html/
cmake-build*
build
obj_dir*
obj_dir*
compile_commands.json
.cache
3 changes: 3 additions & 0 deletions .gitmodules
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
[submodule "dependencies/membox"]
path = dependencies/membox
url = https://github.com/THU-DSP-LAB/membox.git
59 changes: 16 additions & 43 deletions CMakeLists.txt
Original file line number Diff line number Diff line change
@@ -1,51 +1,24 @@
cmake_minimum_required(VERSION 3.22)

set(CMAKE_EXPORT_COMPILE_COMMANDS ON)

set(PROJECT ventus_driver)
project(${PROJECT})

set(CMAKE_CXX_STANDARD 17)
# set(CMAKE_CXX_FLAGS -Wl,--whole-archive -Wl,--no-whole-archive)

include_directories(common)
include_directories(include)
include_directories(devices)
include_directories(devices/verilating_device/page_table)
include_directories(tests)
include_directories(driver)


set(CMAKE_BUILD_TYPE "Debug")

if(CMAKE_BUILD_TYPE AND (CMAKE_BUILD_TYPE STREQUAL "Debug"))
set(CMAKE_CXX_FLAGS_DEBUG "${CMAKE_CXX_FLAGS_DEBUG} -Wall -O0 -g -ggdb")
message("Debug mode:${CMAKE_CXX_FLAGS_DEBUG}")
# add_executable(test_debug ${src_dirs})


elseif(CMAKE_BUILD_TYPE AND (CMAKE_BUILD_TYPE STREQUAL "Release"))
set(CMAKE_CXX_FLAGS_RELEASE "${CMAKE_CXX_FLAGS_RELEASE} -Wall -O3")
message("Release mode:${CMAKE_CXX_FLAGS_RELEASE}")
# add_executable(test_release ${src_dirs})
else()
message("else:${CMAKE_BUILD_TYPE}")
message("else:${CMAKE_CXX_FLAGS_RELEASE}")
# add_executable(test_release ${src_dirs})
endif()

if(EXISTS "${CMAKE_SOURCE_DIR}/test.cpp")
set(CODING_TEST test)
add_executable(${CODING_TEST} test.cpp)
endif()

option(ENABLE_INSTALL "if install driver library to install dir" OFF)

set(DRIVER_LIB_INSTALL_DIR ${CMAKE_INSTALL_PREFIX}/lib/)
message(STATUS "DRIVER_LIB_INSTALL_DIR:" ${DRIVER_LIB_INSTALL_DIR} "\n")

option(ENABLE_VERILATOR "if add verilated rtl device" OFF)
set(CMAKE_CXX_FLAGS_DEBUG "${CMAKE_CXX_FLAGS_DEBUG} -Wall")
set(CMAKE_CXX_FLAGS_RELEASE "${CMAKE_CXX_FLAGS_RELEASE} -Wall")

add_subdirectory(devices)
add_subdirectory(dependencies/membox)
add_subdirectory(common)
add_subdirectory(driver)
if(ENABLE_VERILATOR)
add_subdirectory(tests)
endif()
add_subdirectory(codetests)
add_subdirectory(codetests)

set(DRIVER_PUBLIC_HEADERS
${CMAKE_CURRENT_SOURCE_DIR}/include/ventus.h
${CMAKE_CURRENT_SOURCE_DIR}/common/vt_utils.h
)
install(FILES ${DRIVER_PUBLIC_HEADERS}
DESTINATION include COMPONENT "include"
)
97 changes: 95 additions & 2 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,4 +1,97 @@
# ventus-driver
driver code for [ventus-gpgpu](https://github.com/THU-DSP-LAB/ventus-gpgpu)

To build this repository, see [llvm-ventus](https://github.com/THU-DSP-LAB/llvm-project).
## English
[中文版 Chinese](#中文)

Driver code for Ventus GPGPU project [ventus-gpgpu](https://github.com/THU-DSP-LAB/ventus-gpgpu). It is intended to be used together with other Ventus toolchain projects. See [ventus-env](https://github.com/THU-DSP-LAB/ventus-env).

### Install
- Recommended: use [ventus-env](https://github.com/THU-DSP-LAB/ventus-env) to deploy the Ventus environment and build via the script build-ventus.sh.

- Manual CMake build:
```bash
cmake -G Ninja -B build/ -S . \
-DCMAKE_BUILD_TYPE=RelWithDebInfo \
-DCMAKE_INSTALL_PREFIX=../install \
-DVENTUS_INSTALL_PREFIX=../install \
-DSPIKE_SRC_DIR=../spike \
-DDRIVER_ENABLE_AUTOSELECT=ON \
-DDRIVER_ENABLE_RTLSIM=ON \
-DDRIVER_ENABLE_CYCLESIM=ON
cmake --build build/
cmake --install build/
```

### Usage
This repository provides the driver implementation for Ventus GPGPU, mainly handling memory management and device connectivity.

- Upstream (host): connects to an OpenCL implementation ([POCL](https://github.com/THU-DSP-LAB/pocl)).
- Downstream (devices): supports multiple (simulation) backends:
- Instruction-level simulator [spike](https://github.com/THU-DSP-LAB/ventus-gpgpu-isa-simulator), path: driver/spike_device
- SystemC-based cycle-accurate simulator [cyclesim](https://github.com/THU-DSP-LAB/ventus-gpgpu-cpp-simulator), path: driver/cyclesim_device
- Verilator-based [Chisel RTL](https://github.com/THU-DSP-LAB/ventus-gpgpu) simulation framework [sim-verilator](https://github.com/THU-DSP-LAB/ventus-gpgpu/tree/master/sim-verilator), path: driver/rtlsim_device
- The helper backend driver/auto_select allows choosing a backend via the environment variable VENTUS_BACKEND (see Usage).
- Both upstream and downstream connections are via shared libraries.

This repository builds multiple shared libraries installed into the specified prefix. After configuring environment variables as in [ventus-env](https://github.com/THU-DSP-LAB/ventus-env), you can run OpenCL programs and the driver will be invoked automatically.

### Environment variables
- `VENTUS_BACKEND` selects the device backend. Allowed values: spike/isa, rtl/rtlsim/gpgpu, cycle/cyclesim/systemc/simulator.
- `VENTUS_WAVEFORM=1` enables waveform dump: fst for rtlsim, vcd for cyclesim.
- `VENTUS_WAVEFORM_BEGIN` and `VENTUS_WAVEFORM_END` define a time window to limit waveform dump for rtlsim (speeds up simulation). Not supported by cyclesim.
- `VENTUS_DUMP_RESULT=filename.json` saves all device-to-host copied data and their device addresses into a JSON file for debugging.
- `VENTUS_TIMING_DDR=0` disables DDR timing modeling in cyclesim (enabled by default). RTL does not support DDR timing yet.

### Example
```bash
VENTUS_BACKEND=rtl VENTUS_DUMP_RESULT=app.rtl.json VENTUS_WAVEFORM=1 ./OpenCLapp.out 2>&1 | tee rtl.log
```

---

## 中文
[English Version](#english)

这是[ventus-gpgpu](https://github.com/THU-DSP-LAB/ventus-gpgpu)的驱动程序,目前仅支持仿真环境,需与其他Ventus工具链项目配合使用,参见 [ventus-env](https://github.com/THU-DSP-LAB/ventus-env)。

### Install
推荐使用 [ventus-env](https://github.com/THU-DSP-LAB/ventus-env) 部署 Ventus 环境,使用其中的 build-ventus.sh 脚本来编译安装。

手动 cmake 编译命令:
```bash
cmake -G Ninja -B build/ -S . \
-DCMAKE_BUILD_TYPE=RelWithDebInfo \
-DCMAKE_INSTALL_PREFIX=../install \
-DVENTUS_INSTALL_PREFIX=../install \
-DSPIKE_SRC_DIR=../spike \
-DDRIVER_ENABLE_AUTOSELECT=ON \
-DDRIVER_ENABLE_RTLSIM=ON \
-DDRIVER_ENABLE_CYCLESIM=ON
cmake --build build/
cmake --install build/
```

### Usage
本仓库作为乘影 Ventus GPGPU 的驱动实现,主要完成内存管理与设备连接的功能。
- 向上层连接 OpenCL 实现([POCL](https://github.com/THU-DSP-LAB/pocl))。
- 向底层连接多种(仿真)设备,目前支持:
- 指令级仿真器 [spike](https://github.com/THU-DSP-LAB/ventus-gpgpu-isa-simulator),对应 driver/spike_device
- 基于 SystemC 的周期级仿真器 [cyclesim](https://github.com/THU-DSP-LAB/ventus-gpgpu-cpp-simulator),对应 driver/cyclesim_device
- 基于 Verilator 搭建的 [Chisel RTL](https://github.com/THU-DSP-LAB/ventus-gpgpu) 仿真框架 [sim-verilator](https://github.com/THU-DSP-LAB/ventus-gpgpu/tree/master/sim-verilator),对应 driver/rtlsim_device
- 另有 driver/auto_select,用户可通过环境变量 VENTUS_BACKEND 指定具体底层设备(见 Usage)。
- 向上层与向底层的连接均以动态库链接的形式完成。

本仓库会编译出多个动态库安装到指定目录下。用户参照 [ventus-env](https://github.com/THU-DSP-LAB/ventus-env) 配置好环境变量后运行 OpenCL 程序即可自动调用。

### 环境变量
- VENTUS_BACKEND 选择底层设备,可选值:spike/isa,rtl/rtlsim/gpgpu,cycle/cyclesim/systemc/simulator。
- VENTUS_WAVEFORM=1 时,rtlsim 导出 fst 波形,cyclesim 导出 vcd 波形。
- 设定 VENTUS_WAVEFORM_BEGIN 与 VENTUS_WAVEFORM_END(数字)可使 rtlsim 仅导出该时间段内波形,加速仿真;cyclesim 不支持。
- VENTUS_DUMP_RESULT=filename.json 将所有从 device 端拷回 host 端的数据及其设备端地址保存到指定 JSON 文件,辅助调试。
- VENTUS_TIMING_DDR=0 关闭 cyclesim 中的 DDR 时序仿真(默认开启)。RTL 暂不支持 DDR 时序仿真。

### 示例
```bash
VENTUS_BACKEND=rtl VENTUS_DUMP_RESULT=app.rtl.json VENTUS_WAVEFORM=1 ./OpenCLapp.out 2>&1 | tee rtl.log
```

Empty file removed TODO
Empty file.
20 changes: 20 additions & 0 deletions common/CMakeLists.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
set(PROJECT driver_common_utils)
project(${PROJECT})

file(GLOB_RECURSE SRCS ./loadelf.cpp)

add_library(${PROJECT} STATIC ${SRCS})

target_link_libraries(${PROJECT} PRIVATE elf)
target_link_libraries(${PROJECT} PRIVATE spdlog)
target_link_libraries(${PROJECT} PRIVATE fmt)
target_include_directories(${PROJECT} PUBLIC ${CMAKE_CURRENT_SOURCE_DIR})

set_target_properties(${PROJECT} PROPERTIES OUTPUT_NAME "${PROJECT}")
set_target_properties(${PROJECT} PROPERTIES CLEAN_DIRECT_OUTPUT 1)
set_target_properties(${PROJECT} PROPERTIES POSITION_INDEPENDENT_CODE ON)

# if(ENABLE_INSTALL)
# message(STATUS "DRIVER_LIB_INSTALL_DIR:" ${DRIVER_LIB_INSTALL_DIR})
# install(TARGETS ${PROJECT} LIBRARY DESTINATION ${DRIVER_LIB_INSTALL_DIR} COMPONENT "lib")
# endif()
94 changes: 94 additions & 0 deletions common/loadelf.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,94 @@
#include "loadelf.hpp"
#include <cstdio>
#include <cstdlib>
#include <fcntl.h>
#include <gelf.h>
#include <libelf.h>
#include <memory>
#include <spdlog/spdlog.h>
#include <unistd.h>

// 分析 ELF 文件,返回所有加载到内存中的段信息
std::vector<MemBlock> get_data_from_elf(const char *filename, std::shared_ptr<spdlog::logger> logger) {
std::vector<MemBlock> blocks;

// 初始化 libelf 库
if (elf_version(EV_CURRENT) == EV_NONE) {
logger->error("ELF: cannot initialize libelf");
return std::vector<MemBlock>();
}

// 打开 ELF 文件
int fd = open(filename, O_RDONLY);
if (fd < 0) {
const char *errstr = strerrordesc_np(errno);
logger->error("ELF: cannot open file '{}': {}", filename, errstr);
return std::vector<MemBlock>();
}

// 开始 ELF 处理
Elf *e = elf_begin(fd, ELF_C_READ, nullptr);
if (!e) {
logger->error("ELF: elf_begin failed: {}", elf_errmsg(-1));
close(fd);
return std::vector<MemBlock>();
}

// 读取 ELF 头部
GElf_Ehdr ehdr;
if (gelf_getehdr(e, &ehdr) == nullptr) {
logger->error("ELF: gelf_getehdr failed: {}", elf_errmsg(-1));
elf_end(e);
close(fd);
return std::vector<MemBlock>();
}

// 获取程序头表中的段数量
size_t phnum = 0;
if (elf_getphdrnum(e, &phnum) != 0) {
logger->error("ELF: elf_getphdrnum failed: {}", elf_errmsg(-1));
elf_end(e);
close(fd);
return std::vector<MemBlock>();
}

// 遍历所有程序头
for (size_t i = 0; i < phnum; ++i) {
GElf_Phdr phdr;
if (gelf_getphdr(e, i, &phdr) != &phdr) {
logger->error("ELF: gelf_getphdr header {} failed: {}", i, elf_errmsg(-1));
return std::vector<MemBlock>();
}

// 只考虑加载段
if (phdr.p_type == PT_LOAD) {
MemBlock block;
block.vaddr = phdr.p_vaddr;
block.memsz = phdr.p_memsz;

// 如果段在文件中有初始化数据,则读取数据
if (phdr.p_filesz > 0) {
block.data.resize(phdr.p_filesz);
if (lseek(fd, phdr.p_offset, SEEK_SET) == -1) {
const char *errstr = strerrordesc_np(errno);
logger->error("ELF: failed seeking to offset {}: {}", phdr.p_offset, errstr);
return std::vector<MemBlock>();
} else {
ssize_t bytesRead = read(fd, block.data.data(), phdr.p_filesz);
if (bytesRead != (ssize_t)phdr.p_filesz) {
const char *errstr = strerrordesc_np(errno);
logger->error(
"ELF: failed reading {} bytes data: {}", phdr.p_filesz, errstr
);
return std::vector<MemBlock>();
}
}
}
blocks.push_back(block);
}
}

elf_end(e);
close(fd);
return blocks;
}
16 changes: 16 additions & 0 deletions common/loadelf.hpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
#pragma once

#include <cstdint>
#include <memory>
#include <spdlog/spdlog.h>
#include <vector>

// 解析ELF后返回的需要分配的内存块信息
typedef struct MemBlock {
uint64_t vaddr; // 内存块的起始地址
size_t memsz; // 内存块所需分配大小
std::vector<uint8_t> data; // 此内存块的初始化数据
// 若(filesz=)data.size < memsz则需要补0到memsz大小
} MemBlock;

std::vector<MemBlock> get_data_from_elf(const char *filename, std::shared_ptr<spdlog::logger> logger);
45 changes: 45 additions & 0 deletions common/utils.hpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,45 @@
#include <algorithm>
#include <cctype>
#include <cerrno>
#include <cstdint>
#include <cstdlib>
#include <optional>
#include <string>

inline std::optional<bool> parse_bool(std::string str) {
// transform to lowercase safely (unsigned char cast to avoid UB)
std::transform(str.begin(), str.end(), str.begin(), [](char c) {
return static_cast<char>(std::tolower(c));
});
if (str == "true" || str == "1" || str == "yes" || str == "on") return true;
if (str == "false" || str == "0" || str == "no" || str == "off") return false;
return std::nullopt;
}
inline std::optional<bool> parse_bool(const char *str) {
if (str == nullptr) return std::nullopt;
return parse_bool(std::string(str));
}

inline std::optional<uint64_t> parse_u64(const char *s) {
if (!s || *s == '\0') return std::nullopt;

// 手动处理二进制 0b/0B
if (s[0] == '0' && (s[1] == 'b' || s[1] == 'B')) {
const char *p = s + 2;
if (*p == '\0') return std::nullopt;
uint64_t v = 0;
while (*p == '0' || *p == '1') {
v = (v << 1) | (*p - '0');
++p;
}
if (*p != '\0') return std::nullopt;
return v;
}

errno = 0;
char *endp = nullptr;
// base = 0 自动识别: 0x/0X -> 16, 前导0 -> 8, 否则 -> 10
unsigned long long v = std::strtoull(s, &endp, 0);
if (errno != 0 || endp == s || *endp != '\0') return std::nullopt;
return static_cast<uint64_t>(v);
};
1 change: 1 addition & 0 deletions dependencies/membox
Submodule membox added at fdccb9
Loading