Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
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
78 changes: 78 additions & 0 deletions .github/workflows/build.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,78 @@
name: GitHub Actions
on:
push:
branches:
- master
pull_request:
branches:
- master

jobs:
ubuntu:
runs-on: ubuntu-24.04
steps:
- uses: actions/checkout@v4
- name: Install MPICH
run: |
sudo apt-get update
sudo apt-get install -y mpich libmpich-dev
- name: Configure
run: cmake -S . -B build -DROSS_BUILD_MODELS=ON -DCMAKE_BUILD_TYPE=Debug -DCMAKE_INSTALL_PREFIX=$PWD/install
- name: Build
run: cmake --build build -j
- name: Test
run: ctest --test-dir build --output-on-failure
- name: Install
run: cmake --install build
- name: Upload logs on failure
if: failure()
uses: actions/upload-artifact@v4
with:
name: build-logs
path: |
build/Testing/Temporary/LastTest.log
build/Testing/Temporary/LastTestsFailed.log
build/CMakeFiles/CMakeError.log
build/CMakeFiles/CMakeOutput.log
build/CMakeCache.txt
if-no-files-found: ignore
retention-days: 14

coverage:
runs-on: ubuntu-24.04
steps:
- uses: actions/checkout@v4
- name: Install MPICH and lcov
run: |
sudo apt-get update
sudo apt-get install -y mpich libmpich-dev lcov
- name: Configure with coverage
run: cmake -S . -B build -DROSS_BUILD_MODELS=ON -DCMAKE_BUILD_TYPE=Debug -DROSS_ENABLE_COVERAGE=ON
- name: Build
run: cmake --build build -j
- name: Test
run: ctest --test-dir build --output-on-failure
- name: Collect coverage
run: |
lcov --capture --directory build --output-file coverage.info \
--ignore-errors mismatch,gcov,source,unused
lcov --remove coverage.info \
'/usr/*' \
'*/core/lz4.*' \
'*/models/*' \
--output-file coverage.info \
--ignore-errors unused
lcov --list coverage.info
- name: Upload to Codecov
uses: codecov/codecov-action@v5
with:
files: coverage.info
fail_ci_if_error: false
- name: Upload coverage artifact
if: always()
uses: actions/upload-artifact@v4
with:
name: coverage-info
path: coverage.info
if-no-files-found: ignore
retention-days: 14
2 changes: 2 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -4,3 +4,5 @@ build/
models/*/
!models/phold
*.swp
CLAUDE.local.md
CMakeUserPresets.json
84 changes: 0 additions & 84 deletions .travis.yml

This file was deleted.

94 changes: 94 additions & 0 deletions CLAUDE.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,94 @@
# Project: ROSS

Rensselaer's Optimistic Simulation System — a parallel discrete-event simulator (PDES) written in C, using MPI for distribution. Models are collections of Logical Processes (LPs) that exchange timestamped events. The Time Warp mechanism allows optimistic execution with rollback; ROSS implements this via **reverse computation** (each event handler has a paired reverse handler that undoes its effect) rather than state saving. Downstream consumers include [CODES](https://github.com/codes-org/codes) (which links ROSS via pkg-config) and RISA (in-situ analysis submodule).

## Build

Typical manual configure:

```
cmake -S . -B build -DROSS_BUILD_MODELS=ON -DCMAKE_C_COMPILER=mpicc -DCMAKE_BUILD_TYPE=Debug
cmake --build build -j
cmake --install build
```

Models are **not** built by default — pass `-DROSS_BUILD_MODELS=ON` to include `phold` and any symlinked-in models. `BUILD_TESTING=ON` enables the ctest suite.

MPI is required. The top-level `CMakeLists.txt` does per-arch detection via `CMAKE_SYSTEM_PROCESSOR` and falls back to a `gtod` clock if unrecognized. Set `-DROSS_CLOCK_OVERRIDE=YES` to force the gtod clock.

## Running a model

Models accept `--synch=N` to pick the scheduler:

- `1` sequential, `2` conservative, `3` optimistic, `4` optimistic debug (single-rank), `5` optimistic realtime, `6` rollback-check (single-rank, runs forward then reverse-executes all events to catch missing reverse handlers).

```
./phold --synch=1
mpirun -np 2 ./phold --synch=3 --extramem=100000
./phold --args-file=sample.txt # flags one-per-line
```

`--synch=6` is the go-to when adding/modifying an event handler: it surfaces reverse-computation bugs that optimistic mode might hide.

## Tests

```
ctest --test-dir build # full suite
ctest --test-dir build -R phold_SCHED_Optimistic # single test by regex
ctest --test-dir build -V -R <name> # with output
```

Tests live in `models/phold/CMakeLists.txt` and are generated by the `ROSS_TEST_SCHEDULERS` and `ROSS_TEST_INSTRUMENTATION` functions in `models/CMakeLists.txt`. Each new model variant (e.g. `phold_comm_test`, `phold_gvt_hook_test`) gets the full scheduler matrix applied via these functions. When adding a model or test variant, call these helpers rather than hand-writing `ADD_TEST`.

## Architecture

### Simulation hierarchy (top to bottom)

- **PE** (`tw_pe`, one per MPI rank) — owns the priority queue, the event buffer pool, network driver, and GVT state. Code: [tw-pe.c](core/tw-pe.c), [tw-sched.c](core/tw-sched.c).
- **KP** (`tw_kp`) — Kernel Process, a rollback granularity unit. Multiple KPs per PE; events are committed/rolled back at KP scope. Code: [tw-kp.c](core/tw-kp.c).
- **LP** (`tw_lp`) — the model-facing object. Each LP has a `tw_lptype` vtable (init/pre-run/event/rc-event/commit/final/map). Code: [tw-lp.c](core/tw-lp.c).

Type definitions: [core/ross-types.h](core/ross-types.h). Public API entry point: [core/ross.h](core/ross.h).

### Pluggable components

Compiled-in choices are hard-coded in `CMakeLists.txt`:

- **Queue** = `splay` ([core/queue/splay.c](core/queue/splay.c)). Others (`calendar`, `heap`, `kp_splay`) are `.old` and disabled.
- **Random** = `clcg4` ([core/rand-clcg4.c](core/rand-clcg4.c)).
- **Network** = `mpi` ([core/network-mpi.c](core/network-mpi.c)).
- **GVT** = `mpi_allreduce` ([core/gvt/mpi_allreduce.c](core/gvt/mpi_allreduce.c)). The `7oclock` alternative is `.old`.
- **Clock** — auto-picked per `CMAKE_SYSTEM_PROCESSOR` from [core/clock/](core/clock/).

Optional subsystems:

- **AVL tree vs hash** for remote-event dedup in optimistic mode (`AVL_TREE=ON` default; files `avl_tree.c`, `hash-quadratic.c`).
- **RIO** — checkpoint/restart ([core/rio/](core/rio/)), opt-in via `USE_RIO=ON`.
- **Instrumentation** ([core/instrumentation/](core/instrumentation/)) — ships ROSS-internal analysis LPs; enabled by runtime flags `--engine-stats`, `--event-trace`, `--model-stats`, `--kp-data`, `--lp-data`.
- **check-revent** ([core/check-revent/](core/check-revent/)) — backs `--synch=6` sequential rollback validation.

Damaris/RISA in-situ vis is currently disabled — the `USE_DAMARIS` CMake option has been removed pending a follow-up that strips the inert C source paths and the `core/risa/` submodule.

### Memory discipline

In `ROSS_INTERNAL` scope (core/*.c files), `malloc`/`calloc`/`realloc`/`free`/`strdup` are macro-poisoned in [core/ross-base.h](core/ross-base.h) — use `tw_calloc` and the event buffer pool (`tw_event_new` / `tw_event_send`) instead. Events come from a preallocated pool sized by `--nevents` and `--extramem`. Don't allocate from the system heap inside event handlers.

### Writing a model (forward + reverse)

Every event handler must have a paired reverse handler. The reverse handler has to exactly undo state mutations the forward one performed — including any RNG draws (call the same `tw_rand_*` reverse variant) and any `tw_event_send` calls (rollback walks them automatically, but the count must match). The `tw_bf` bitfield argument to the forward handler is the standard place to record which branches ran so the reverse handler can conditionally undo.

## Code style

The de facto C style in `core/` is:

- **Naming**: `snake_case` with a `tw_` prefix for the public ROSS surface — functions (`tw_pe_init`), structs (`tw_pe`), typedefs. Function-pointer typedefs end in `_f` (e.g. `init_f`, `event_f`, `revent_f`, `map_f`). Local variables are plain `snake_case`.
- **typedef pattern**: `struct tw_foo { ... }; typedef struct tw_foo tw_foo;` — struct tag and typedef name match, both `tw_`-prefixed.
- **Header guards**: `#ifndef INC_<filename>_h` / `#define INC_<filename>_h` / `#endif`. Not `#pragma once`.
- **`static` on file-local functions**: applied consistently. Internal helpers in a `.c` file should be `static`.
- **Includes**: system headers first (stdio/stdlib/string/assert/mpi), then project headers. Grouped, not strictly alphabetized.
- **Line length**: soft ~100 chars. No hard cap.
- **Comments**: both `//` and `/* */` appear; `/** ... */` Doxygen-style is used for some function-level docs but isn't required.

## Consumer compatibility (CODES)

CODES discovers ROSS via `pkg_check_modules(ROSS REQUIRED IMPORTED_TARGET ross)` using `ross.pc`. It relies on the `ROSS_INCLUDE_DIRS` variable and links `PkgConfig::ROSS`. Any install-layout change (header paths, pkg-config contents) must preserve that surface or CODES breaks.
22 changes: 14 additions & 8 deletions CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -39,14 +39,6 @@ ENDIF("${isSystemDir}" STREQUAL "-1")

# end of spack-related addition

# We probably don't want this to run on every build.
option(COVERALLS "Generate coveralls data" OFF)

if (COVERALLS)
include(Coveralls)
coveralls_turn_on_coverage()
endif()

# Priority Queue Implementation
SET(QUEUE splay)
# Other queue implementations are no longer supported.
Expand Down Expand Up @@ -156,6 +148,20 @@ ELSE(MPI_C_FOUND)
MESSAGE(" Or force CMake to build using the correct compiler (`export CC=mpicc`)")
ENDIF(MPI_C_FOUND)

# Code coverage instrumentation (GCC/Clang only). Applied at directory scope
# so flags propagate to core/ and models/. Collect with lcov/gcovr after ctest.
option(ROSS_ENABLE_COVERAGE "Enable code coverage instrumentation" OFF)
mark_as_advanced(ROSS_ENABLE_COVERAGE)
if(ROSS_ENABLE_COVERAGE)
if(NOT CMAKE_C_COMPILER_ID MATCHES "^(GNU|Clang|AppleClang)$")
message(FATAL_ERROR
"ROSS_ENABLE_COVERAGE requires GCC or Clang; got ${CMAKE_C_COMPILER_ID}")
endif()
message(STATUS "Code coverage enabled (--coverage)")
add_compile_options(--coverage)
add_link_options(--coverage)
endif()

# ROSS Core code
ADD_SUBDIRECTORY(core)

Expand Down
2 changes: 2 additions & 0 deletions codecov.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
codecov:
token: 522b5c25-dd24-4085-86df-5b88ffad91a4
24 changes: 0 additions & 24 deletions core/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -116,14 +116,6 @@ IF(USE_RIO)
INCLUDE_DIRECTORIES(rio)
ENDIF(USE_RIO)

# Damaris I/O and data management
OPTION(USE_DAMARIS "Build with Damaris library (for in situ vis/analysis)?" OFF)
if (USE_DAMARIS)
ADD_SUBDIRECTORY(risa)
INCLUDE_DIRECTORIES(${DAMARIS_INCLUDE})
SET(ross_srcs ${ross_srcs} ${ROSS_Damaris_SOURCE_DIR}/core/damaris.h)
ENDIF(USE_DAMARIS)

# Use deterministic unbiased RNG tiebreaker for event ties
OPTION(USE_RAND_TIEBREAKER "Build with deterministic unbiased tiebreaker for event ties" ON)

Expand Down Expand Up @@ -154,18 +146,6 @@ SET_TARGET_PROPERTIES(ROSS PROPERTIES OUTPUT_NAME ROSS)
TARGET_LINK_LIBRARIES(ROSS ${ROSS_EXTERNAL_LIBS})
TARGET_INCLUDE_DIRECTORIES(ROSS INTERFACE ${MPI_C_INCLUDE_PATH})

if (COVERALLS)
set(COVERAGE_SRCS ${ross_srcs})
# Don't check coverage on lz4
list(REMOVE_ITEM COVERAGE_SRCS lz4.h lz4.c)

# Create the coveralls target.
coveralls_setup(
"${COVERAGE_SRCS}" # The source files.
OFF) # If we should upload.

endif()

# Build Specific Config Header
CONFIGURE_FILE(config.h.in config.h)
SET(ross_srcs ${ross_srcs} config.h)
Expand All @@ -174,17 +154,13 @@ SET_SOURCE_FILES_PROPERTIES(${CMAKE_CURRENT_BINARY_DIR}/config.h PROPERTIES GENE


# CODES config bin
SET(ROSS_CC $ENV{CC})
SET(ROSS_CXX $ENV{CXX})
STRING(REPLACE " " "\\ " CMAKE_INSTALL_PREFIX_ESCAPED "\"${CMAKE_INSTALL_PREFIX}\"")
CONFIGURE_FILE(ross-config.in ross-config @ONLY)
CONFIGURE_FILE(ross.pc.in ross.pc @ONLY)
SET_SOURCE_FILES_PROPERTIES(${CMAKE_CURRENT_SOURCE_DIR}/ross.pc.in PROPERTIES GENERATED FALSE)
SET_SOURCE_FILES_PROPERTIES(${CMAKE_CURRENT_BINARY_DIR}/ross.pc PROPERTIES GENERATED TRUE)


# Make Install
INSTALL(FILES ${ROSS_BINARY_DIR}/ross-config DESTINATION bin PERMISSIONS OWNER_READ OWNER_WRITE OWNER_EXECUTE GROUP_READ GROUP_EXECUTE WORLD_READ WORLD_EXECUTE)
INSTALL(FILES ${ROSS_BINARY_DIR}/config.h DESTINATION include)
INSTALL(DIRECTORY ${ROSS_SOURCE_DIR}/ DESTINATION include FILES_MATCHING PATTERN "*.h")
INSTALL(TARGETS ROSS EXPORT ROSS-targets DESTINATION lib)
Expand Down
Loading