Skip to content

Commit ca8265e

Browse files
committed
Merge branch 'main' of github.com:SlugLab/CXLMemSim
2 parents 9d3c397 + 41432f8 commit ca8265e

9 files changed

Lines changed: 233 additions & 26 deletions

File tree

CMakeLists.txt

Lines changed: 49 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,9 @@
11
cmake_minimum_required(VERSION 3.25.0)
22
project(CXLMemSim VERSION 0.1.0)
33

4+
option(CXLMEMSIM_BUILD_MICROBENCHMARKS "Build microbenchmarks" ON)
5+
option(CXLMEMSIM_ENABLE_RDMA "Enable RDMA transport when libraries are available" ON)
6+
47
if ("${CMAKE_CXX_COMPILER_ID}" STREQUAL "GNU")
58
add_compile_options (-fdiagnostics-color=always)
69
elseif ("${CMAKE_CXX_COMPILER_ID}" STREQUAL "Clang")
@@ -20,17 +23,42 @@ add_compile_definitions(SPDLOG_USE_STD_FORMAT)
2023
# Use header-only spdlog to avoid library mismatch
2124
add_compile_definitions(SPDLOG_HEADER_ONLY)
2225

23-
add_subdirectory(microbench)
26+
if(CXLMEMSIM_BUILD_MICROBENCHMARKS)
27+
add_subdirectory(microbench)
28+
endif()
2429

2530
list(APPEND CMAKE_PREFIX_PATH ${CMAKE_BINARY_DIR})
2631

2732
find_package(cxxopts REQUIRED)
2833
find_package(spdlog REQUIRED)
29-
file(GLOB_RECURSE SOURCE_FILES src/cxl*.cpp src/policy.cpp src/helper.cpp src/incore.cpp src/uncore.cpp src/perf.cpp src/monitor.cpp)
3034

3135
execute_process(COMMAND uname -r OUTPUT_VARIABLE arch OUTPUT_STRIP_TRAILING_WHITESPACE)
3236
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Wall -fPIC -pthread")
33-
set(CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} -latomic")
37+
38+
find_library(ATOMIC_LIB atomic)
39+
find_library(RT_LIB rt)
40+
if(NOT ATOMIC_LIB)
41+
set(ATOMIC_LIB "" CACHE STRING "libatomic path" FORCE)
42+
endif()
43+
if(NOT RT_LIB)
44+
set(RT_LIB "" CACHE STRING "librt path" FORCE)
45+
endif()
46+
47+
set(SOURCE_FILES
48+
src/cxlcontroller.cpp
49+
src/cxlendpoint.cpp
50+
src/policy.cpp
51+
src/helper.cpp
52+
)
53+
54+
if(CMAKE_SYSTEM_NAME STREQUAL "Linux")
55+
list(APPEND SOURCE_FILES
56+
src/incore.cpp
57+
src/uncore.cpp
58+
src/perf.cpp
59+
src/monitor.cpp
60+
)
61+
endif()
3462

3563

3664
# Create a static library of CXL core functionality
@@ -44,31 +72,40 @@ set_target_properties(cxlmemsim_latency PROPERTIES
4472
RUNTIME_OUTPUT_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR}
4573
)
4674

47-
find_library(RDMACM_LIB rdmacm)
48-
find_library(IBVERBS_LIB ibverbs)
49-
message(STATUS "RDMA support enabled: rdmacm=${RDMACM_LIB} ibverbs=${IBVERBS_LIB}")
50-
add_compile_definitions(HAS_RDMA)
51-
set(RDMA_LIBS ${RDMACM_LIB} ${IBVERBS_LIB})
75+
set(RDMA_LIBS)
76+
if(CXLMEMSIM_ENABLE_RDMA AND CMAKE_SYSTEM_NAME STREQUAL "Linux")
77+
find_library(RDMACM_LIB rdmacm)
78+
find_library(IBVERBS_LIB ibverbs)
79+
if(RDMACM_LIB AND IBVERBS_LIB)
80+
message(STATUS "RDMA support enabled: rdmacm=${RDMACM_LIB} ibverbs=${IBVERBS_LIB}")
81+
add_compile_definitions(HAS_RDMA)
82+
set(RDMA_LIBS ${RDMACM_LIB} ${IBVERBS_LIB})
83+
else()
84+
message(STATUS "RDMA support disabled: rdmacm or ibverbs not found")
85+
endif()
86+
else()
87+
message(STATUS "RDMA support disabled")
88+
endif()
5289

5390
# Server library (shared between server executable and tests)
5491
set(SERVER_LIB_SOURCES src/shared_memory_manager.cc src/shm_communication.cpp src/distributed_server.cpp src/tcp_communication.cpp src/rdma_communication.cpp src/hdm_decoder.cpp src/coherency_engine.cpp)
5592
add_library(cxlmemsim_server_lib STATIC ${SERVER_LIB_SOURCES})
5693
target_include_directories(cxlmemsim_server_lib PUBLIC include src ${cxxopts_INCLUDE_DIR} ${spdlog_INCLUDE_DIR})
57-
target_link_libraries(cxlmemsim_server_lib cxlmemsim cxxopts::cxxopts spdlog::spdlog_header_only rt ${RDMA_LIBS})
94+
target_link_libraries(cxlmemsim_server_lib cxlmemsim cxxopts::cxxopts spdlog::spdlog_header_only ${RT_LIB} ${RDMA_LIBS})
5895

5996
# Build server (uses server library + main)
6097
add_executable(cxlmemsim_server src/main_server.cc)
6198
target_include_directories(cxlmemsim_server PRIVATE include src ${cxxopts_INCLUDE_DIR} ${spdlog_INCLUDE_DIR})
62-
target_link_libraries(cxlmemsim_server cxlmemsim_server_lib cxlmemsim cxxopts::cxxopts spdlog::spdlog_header_only rt)
99+
target_link_libraries(cxlmemsim_server cxlmemsim_server_lib cxlmemsim cxxopts::cxxopts spdlog::spdlog_header_only ${RT_LIB} ${ATOMIC_LIB})
63100

64101
# Distributed SHM test
65102
add_executable(test_distributed_shm tests/test_distributed_shm.cpp)
66103
target_include_directories(test_distributed_shm PRIVATE include src ${cxxopts_INCLUDE_DIR} ${spdlog_INCLUDE_DIR})
67-
target_link_libraries(test_distributed_shm cxlmemsim_server_lib cxlmemsim cxxopts::cxxopts spdlog::spdlog_header_only rt)
104+
target_link_libraries(test_distributed_shm cxlmemsim_server_lib cxlmemsim cxxopts::cxxopts spdlog::spdlog_header_only ${RT_LIB} ${ATOMIC_LIB})
68105

69106
# Installation targets
70107
install(TARGETS cxlmemsim_server
71108
RUNTIME DESTINATION bin)
72109

73110
install(FILES include/tcp_communication.h include/rdma_communication.h
74-
DESTINATION include/cxlmemsim)
111+
DESTINATION include/cxlmemsim)

README.md

Lines changed: 83 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -322,6 +322,89 @@ libnvcuda.so.1
322322
libnvcuda.so
323323
```
324324

325+
## Packaged QEMU/Spack Flow
326+
327+
For macOS and repeatable QEMU smoke tests, use the companion Spack environment from the Ocean Spack fork. That environment builds the x86_64 CXL-capable QEMU tree, builds `cxlmemsim_server`, installs launch scripts, and documents the runtime variables used by QEMU and the server.
328+
329+
```bash
330+
git clone https://github.com/vickiegpt/spack.git ocean-spack
331+
cd ocean-spack
332+
source share/spack/setup-env.sh
333+
spack env activate ./share/spack/environments/cxlmemsim
334+
spack concretize -f
335+
spack install
336+
spack load cxlmemsim
337+
```
338+
339+
The detailed usage document is installed in the Spack checkout at:
340+
341+
```text
342+
share/spack/environments/cxlmemsim/README.md
343+
```
344+
345+
After loading the package, download the guest kernel and disk image:
346+
347+
```bash
348+
cxlmemsim-download-qemu-image
349+
```
350+
351+
The default image directory is `CXL_QEMU_IMAGE_DIR`. To keep the raw guest disk at 4 GB:
352+
353+
```bash
354+
qemu-img resize "$CXL_QEMU_IMAGE_DIR/qemu.img" 4G
355+
cp "$CXL_QEMU_IMAGE_DIR/qemu.img" "$CXL_QEMU_IMAGE_DIR/qemu1.img"
356+
```
357+
358+
Launch the default guest:
359+
360+
```bash
361+
qemu_launch_cxl.sh
362+
```
363+
364+
Launch the second guest image:
365+
366+
```bash
367+
qemu_launch_cxl1.sh
368+
```
369+
370+
The launcher reads the following runtime variables:
371+
372+
| Variable | Default | Meaning |
373+
| --- | --- | --- |
374+
| `CXL_TRANSPORT_MODE` | `shm` | QEMU transport mode: `shm` or `tcp`. |
375+
| `CXL_MEMSIM_HOST` | `127.0.0.1` | Local host for TCP mode. |
376+
| `CXL_MEMSIM_PORT` | `9999` | Local TCP server port. |
377+
| `CXL_PGAS_SHM` | `/cxlmemsim_pgas` | POSIX shared-memory object used by QEMU SHM mode. |
378+
| `CXL_MEMSIM_SERVER_BINARY` | package `bin/cxlmemsim_server` | Server binary started before QEMU. |
379+
| `CXL_MEMSIM_SERVER_AUTOSTART` | `auto` | Set to `1` to require server startup or `0` to disable it. |
380+
381+
QEMU's `shm` transport uses the PGAS shared-memory protocol, so the packaged launcher maps `CXL_TRANSPORT_MODE=shm` to the server's `--comm-mode pgas-shm`.
382+
383+
Shared-memory launch:
384+
385+
```bash
386+
CXL_TRANSPORT_MODE=shm \
387+
CXL_PGAS_SHM=/cxlmemsim_pgas \
388+
qemu_launch_cxl.sh
389+
```
390+
391+
TCP launch on the local port:
392+
393+
```bash
394+
CXL_TRANSPORT_MODE=tcp \
395+
CXL_MEMSIM_HOST=127.0.0.1 \
396+
CXL_MEMSIM_PORT=9999 \
397+
qemu_launch_cxl.sh
398+
```
399+
400+
Inside the guest, quick checks are:
401+
402+
```bash
403+
lspci | grep -i cxl
404+
dmesg | grep -i cxl
405+
ls /sys/bus/cxl/devices
406+
```
407+
325408
## Running CXLMemSim Server
326409

327410
Basic Type 3 server:

include/helper.h

Lines changed: 26 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -12,21 +12,41 @@
1212
#ifndef CXLMEMSIM_HELPER_H
1313
#define CXLMEMSIM_HELPER_H
1414

15+
#if defined(__linux__)
16+
#define CXLMEMSIM_HAS_LINUX_PERF 1
1517
#include "incore.h"
1618
#include "uncore.h"
19+
#include <linux/perf_event.h>
20+
#else
21+
#define CXLMEMSIM_HAS_LINUX_PERF 0
22+
struct perf_event_attr;
23+
#endif
24+
25+
#if defined(__x86_64__) || defined(__i386__)
26+
#include <x86intrin.h>
27+
#else
28+
#include <atomic>
29+
#endif
30+
31+
#include <array>
1732
#include <cstdint>
1833
#include <filesystem>
19-
#include <linux/perf_event.h>
2034
#include <ranges>
2135
#include <spdlog/spdlog.h>
36+
#include <string>
37+
#include <sys/types.h>
38+
#include <tuple>
2239
#include <vector>
23-
#include <x86intrin.h>
2440

2541
#define PAGE_SIZE 4096
2642
#define DATA_SIZE PAGE_SIZE
2743
#define MMAP_SIZE (PAGE_SIZE + DATA_SIZE)
2844

45+
#if defined(__x86_64__) || defined(__i386__)
2946
#define barrier() _mm_mfence()
47+
#else
48+
#define barrier() std::atomic_thread_fence(std::memory_order_seq_cst)
49+
#endif
3050

3151
/* CPU Models */
3252
enum {
@@ -102,8 +122,10 @@ struct Elem {
102122

103123
class PMUInfo {
104124
public:
125+
#if CXLMEMSIM_HAS_LINUX_PERF
105126
std::vector<Uncore> chas;
106127
std::vector<Incore> cpus;
128+
#endif
107129
Helper *helper;
108130
PMUInfo(pid_t pid, Helper *h, PerfConfig *perf_config);
109131
~PMUInfo();
@@ -132,6 +154,8 @@ class Helper {
132154
const std::vector<uint64_t> &perf_conf1, const std::vector<uint64_t> &perf_conf2);
133155
};
134156

157+
#if CXLMEMSIM_HAS_LINUX_PERF
135158
long perf_event_open(perf_event_attr *event_attr, pid_t pid, int cpu, int group_fd, unsigned long flags);
159+
#endif
136160

137161
#endif // CXLMEMSIM_HELPER_H

include/lbr.h

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -21,8 +21,18 @@
2121

2222
#include "cxlcontroller.h"
2323
#include "helper.h"
24+
#include <cstdint>
25+
#if CXLMEMSIM_HAS_LINUX_PERF
2426
#include <linux/perf_event.h>
2527
#include <sys/mman.h>
28+
#else
29+
struct perf_event_header {
30+
uint32_t type;
31+
uint16_t misc;
32+
uint16_t size;
33+
};
34+
struct perf_event_mmap_page;
35+
#endif
2636
class CXLController; // Forward declaration
2737

2838
struct lbr {

include/pebs.h

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,11 @@
1515
#include "helper.h"
1616
#include <cstdint>
1717
#include <cxlcontroller.h>
18+
#if CXLMEMSIM_HAS_LINUX_PERF
1819
#include <sys/mman.h>
20+
#else
21+
struct perf_event_mmap_page;
22+
#endif
1923
#include <sys/types.h>
2024

2125
class PEBS {

src/cxlcontroller.cpp

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,6 @@
1111

1212
#include "cxlcontroller.h"
1313
#include "lbr.h"
14-
#include "monitor.h"
1514
#include "../include/distributed_server.h"
1615

1716
void CXLController::insert_end_point(CXLMemExpander *end_point) { this->cur_expanders.emplace_back(end_point); }
@@ -674,4 +673,4 @@ double CXLController::calculate_distributed_latency(
674673
}
675674

676675
return base_latency + network_latency + coherency_latency;
677-
}
676+
}

0 commit comments

Comments
 (0)