Skip to content

Commit f36eb79

Browse files
authored
Add sysemu support with compile time flag -DGGML_ET_SYSEMU=ON (ggml-org#6)
* Example using ET-Soc-1 emulator configuration Example usage: ```bash cmake -B build -DGGML_CUDA=OFF -DGGML_ET=ON -DLLAMA_CURL=OFF -DGGML_CCACHE=ON cmake --build build --config Release -j $(nproc) time ./build/bin/test-backend-ops ./build/bin/llama-server \ --model Qwen3-0.6B-Q8_0.gguf \ --alias Qwen3-0.6B-Q8_0 \ -fa 0 \ --ctx-size 1024 \ --no-warmup \ --host 127.0.0.1 \ --port 8080 ```
1 parent 756d5a1 commit f36eb79

File tree

4 files changed

+101
-1
lines changed

4 files changed

+101
-1
lines changed

docs/backend/ET.md

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -83,6 +83,12 @@ cmake --build build --config Release
8383
# cmake --install build
8484
```
8585

86+
Build targeting sysemu backend instead of physical hardware:
87+
```sh
88+
cmake -B build -DGGML_ET=ON -DGGML_ET_SYSEMU=ON
89+
cmake --build build --config Release
90+
```
91+
8692
### III. Run
8793

8894
Run llama.cpp binaries as usual. (Of course, please make sure you have the

ggml/CMakeLists.txt

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -245,6 +245,7 @@ set (GGML_SYCL_DEVICE_ARCH "" CACHE STRING
245245
"ggml: sycl device architecture")
246246

247247
option(GGML_ET "ggml: use ET backend" OFF)
248+
option(GGML_ET_SYSEMU "ggml: use ET backend via sysemu" OFF)
248249

249250
option(GGML_OPENCL "ggml: use OpenCL" OFF)
250251
option(GGML_OPENCL_PROFILING "ggml: use OpenCL profiling (increases overhead)" OFF)

ggml/src/ggml-et/CMakeLists.txt

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,14 @@ else()
88
set(ET_PLATFORM_PATH "/opt/et")
99
endif()
1010

11+
# Use sysemu for ET backend if compiled with `-DGGML_ET_SYSEMU=ON`
12+
if(GGML_ET_SYSEMU)
13+
message(STATUS "Using ET backend with sysemu instead of hardware")
14+
add_compile_definitions(GGML_ET_SYSEMU=1)
15+
else()
16+
message(STATUS "Using ET backend with hardware device")
17+
endif()
18+
1119
# Add ET platform CMake modules and config files to search paths
1220
list(APPEND CMAKE_PREFIX_PATH ${ET_PLATFORM_PATH}/lib/cmake)
1321
list(APPEND CMAKE_MODULE_PATH ${ET_PLATFORM_PATH}/lib/cmake)

ggml/src/ggml-et/ggml-et.cpp

Lines changed: 86 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,16 @@
1111
#include <cstring>
1212
#include <vector>
1313

14+
#if __has_include(<filesystem>)
15+
#include <filesystem>
16+
namespace fs = std::filesystem;
17+
#elif __has_include(<experimental/filesystem>)
18+
#include <experimental/filesystem>
19+
namespace fs = std::experimental::filesystem;
20+
#else
21+
#error "cannot include the filesystem library"
22+
#endif
23+
1424
/*
1525
ET Driver.
1626
@@ -25,6 +35,72 @@ static struct ggml_et_driver {
2535
bool profiling_enabled = false;
2636
} _drv;
2737

38+
// Check at runtime environment variables for paths likely holding ET toolchain with sysemu elf files
39+
std::string ggml_et_get_default_et_path() {
40+
// List of environment variables to check in order of preference
41+
const char* const env_vars[] = {"ET_TOOLCHAIN", "TOOLCHAIN_ROOT"};
42+
43+
for (const char* var : env_vars) {
44+
if (const char* et_path = std::getenv(var)) {
45+
if (et_path && *et_path != '\0') {
46+
return fs::path(et_path).string();
47+
}
48+
}
49+
}
50+
51+
// Otherwise assume default
52+
return fs::path("/opt/et").string();
53+
}
54+
55+
// config when using sysemu instead of PCIe hardware device
56+
// adapted from `ainekko/et-platform/esperanto-tools-libs/tools/src/bench.cpp`
57+
inline auto ggml_et_get_default_sysemu_options() {
58+
constexpr uint64_t kSysEmuMaxCycles = std::numeric_limits<uint64_t>::max();
59+
constexpr uint64_t kSysEmuMinionShiresMask = 0x1FFFFFFFFu;
60+
const std::string et_path = ggml_et_get_default_et_path() + "/";
61+
62+
emu::SysEmuOptions sysEmuOptions;
63+
64+
// Construct all paths
65+
sysEmuOptions.bootromTrampolineToBL2ElfPath = et_path + "lib/esperanto-fw/BootromTrampolineToBL2/BootromTrampolineToBL2.elf";
66+
sysEmuOptions.spBL2ElfPath = et_path + "lib/esperanto-fw/ServiceProcessorBL2/fast-boot/ServiceProcessorBL2_fast-boot.elf";
67+
sysEmuOptions.machineMinionElfPath = et_path + "lib/esperanto-fw/MachineMinion/MachineMinion.elf";
68+
sysEmuOptions.masterMinionElfPath = et_path + "lib/esperanto-fw/MasterMinion/MasterMinion.elf";
69+
sysEmuOptions.workerMinionElfPath = et_path + "lib/esperanto-fw/WorkerMinion/WorkerMinion.elf";
70+
sysEmuOptions.executablePath = et_path + "bin/sys_emu";
71+
72+
// Check that each path has a valid existing non-zero file otherwise emulator just silently hangs
73+
const std::vector<std::string> required_files = {
74+
sysEmuOptions.bootromTrampolineToBL2ElfPath,
75+
sysEmuOptions.spBL2ElfPath,
76+
sysEmuOptions.machineMinionElfPath,
77+
sysEmuOptions.masterMinionElfPath,
78+
sysEmuOptions.workerMinionElfPath,
79+
sysEmuOptions.executablePath,
80+
};
81+
82+
for (const auto& file : required_files) {
83+
if (!fs::exists(file) || fs::file_size(file) == 0) {
84+
// Check that each path has a valid existing non-zero file otherwise emulator just silently hangs
85+
GGML_LOG_ERROR("ET: Unable to find required sysemu file: %s\n", file.c_str());
86+
GGML_LOG_ERROR("ET: Confirm et-platform is correctly installed at configured path.\n");
87+
exit(1);
88+
}
89+
}
90+
91+
sysEmuOptions.runDir = (fs::current_path().string() + "/");
92+
sysEmuOptions.maxCycles = kSysEmuMaxCycles;
93+
sysEmuOptions.minionShiresMask = kSysEmuMinionShiresMask;
94+
sysEmuOptions.puUart0Path = sysEmuOptions.runDir + "pu_uart0_tx.log";
95+
sysEmuOptions.puUart1Path = sysEmuOptions.runDir + "pu_uart1_tx.log";
96+
sysEmuOptions.spUart0Path = sysEmuOptions.runDir + "spio_uart0_tx.log";
97+
sysEmuOptions.spUart1Path = sysEmuOptions.runDir + "spio_uart1_tx.log";
98+
sysEmuOptions.startGdb = false;
99+
sysEmuOptions.memcheck = false;
100+
101+
return sysEmuOptions;
102+
}
103+
28104
// Forward declaration
29105
static void ggml_et_driver_cleanup();
30106

@@ -33,7 +109,16 @@ static bool ggml_et_driver_init() {
33109
assert(_drv.device_layer != nullptr);
34110
} else {
35111
try {
36-
_drv.device_layer = dev::IDeviceLayer::createPcieDeviceLayer();
112+
#if defined GGML_ET_SYSEMU && GGML_ET_SYSEMU
113+
// For emulator device using sysEmuOptions provided by function above enabled compiling with `-DGGML_ET_SYSEMU=ON`
114+
GGML_LOG_INFO("ET: Attempting to initialize sysemu device loading firmware from %s\n", ggml_et_get_default_et_path().c_str());
115+
_drv.device_layer = dev::IDeviceLayer::createSysEmuDeviceLayer(ggml_et_get_default_sysemu_options());
116+
#else
117+
// For physical PCIe device
118+
GGML_LOG_INFO("ET: Attempting to initialize PCIe hardware device\n");
119+
_drv.device_layer = dev::IDeviceLayer::createPcieDeviceLayer();
120+
#endif
121+
37122
_drv.runtime = rt::IRuntime::create(_drv.device_layer);
38123
GGML_LOG_INFO("ET: FOUND %d devices!\n", _drv.device_layer->getDevicesCount());
39124

0 commit comments

Comments
 (0)